library(dplyr)
library(tidyr)
#could i look at PRIMPAY and HLTHINS columns to investigate moral hazard on the part of treatment centers for patients with certain insurance/payment characteristics (longer stays)?
admission_cols <- c("CASEID", "PREG", "STFIPS", # state ID
"SERVICES", # type of treatment / service setting
"PSOURCE", # method of referral to treatment
"NOPRIOR", # prior admissions to treatment
"SUB1", "ROUTE1", "FREQ1", "FRSTUSE1", # characteristics of their primary substance, method and frequency of use (could also include second substances)
"HLTHINS", "PRIMPAY", # payment details of interest
"REASON", # reason for discharge
"LOS" #length of stay
)
nssumhs2021 <- read.csv("../Data/NSUMHSS/NSUMHSS_2021_PUF_CSV.csv")
nssumhs2022 <- read.csv("../Data/NSUMHSS/NSUMHSS_2022_PUF_CSV.csv")
nssumhs2023 <- read.csv("../Data/NSUMHSS/NSUMHSS_2023_PUF_CSV.csv")
head(nssumhs2021)
table(nssumhs2021$OWNERSHP) #M and L are missing data
1 2 3 4 5 6 L M
7370 11828 735 1109 215 600 479 10035
table(nssumhs2021$TREATMT_SU) #according to documentation, the TREATMT_SU question asks whether they offer Substance use treatment
0 1 L M
939 16776 4687 9969
#we can filter to where the answer is "1" for yes (not 0 for no, L for logical skip, nor M for missing)
clean_nssumhs <- function(df){
clean_df <- df %>%
#filter to where TREATMT_SU is 1 , meaning they provide substance use treatment
filter(TREATMT_SU == 1) %>%
#rename LOCATIONSTATE to STATE to match NSSATS
rename(STATE = LOCATIONSTATE) %>%
#replace M and L in ownership column with missing (na)
#mutate(OWNERSHP = ifelse(is.na(OWNERSHP), NA, OWNERSHP)) %>%
#alternatively can filter out missing ownership columns
filter((OWNERSHP != "M") & (OWNERSHP != "L")) %>%
#cast ownership to integer
mutate(OWNERSHP = as.integer(OWNERSHP))
return(clean_df)
}
clean_nssumhs2021 <- clean_nssumhs(nssumhs2021)
clean_nssumhs2022 <- clean_nssumhs(nssumhs2022)
clean_nssumhs2023 <- clean_nssumhs(nssumhs2023)
#nssats2009 <- read.csv("N-SSATS-2009-DS0001-bndl-data-tsv/N-SSATS-2009-DS0001-data/N-SSATS-2009-DS0001-data-excel.csv")
nssats2014 <- read.csv("../Data/NSSATS/N-SSATS-2014-DS0001-bndl-data-tsv/N-SSATS-2014-DS0001-data/N-SSATS-2014-DS0001-data-excel.csv")
nssats2015 <- read.csv("../Data/NSSATS/N-SSATS-2015-DS0001-bndl-data-tsv/N-SSATS-2015-DS0001-data/N-SSATS-2015-DS0001-data-excel.csv")
nssats2016 <- read.csv("../Data/NSSATS/NSSATSPUF_2016.csv")
nssats2017 <- read.csv("../Data/NSSATS/NSSATS_PUF_2017_CSV.csv")
nssats2018 <- read.csv("../Data/NSSATS/NSSATS_PUF_2018_CSV.csv")
nssats2019 <- read.csv("../Data/NSSATS/NSSATS_PUF_2019_CSV.csv")
nssats2020 <- read.csv("../Data/NSSATS/NSSATS_PUF_2020_CSV.csv")
head(nssats2015)
Data cleaning on all dfs
profit_types <- c("Forprofit", "Nonprofit", "Government", "Government", "Government", "Government")
# Function to append a number to column names (from ChatGPT)
append_number <- function(name, num) {
paste(name, num, sep = "_")
}
#year_dfs <- list(nssats2014, nssats2015, nssats2016, nssats2017, nssats2018, nssats2019)#, nssats2020)
year_dfs <- list(nssats2014, nssats2015, nssats2016, nssats2017, nssats2018, nssats2019, nssats2020,
clean_nssumhs2021, clean_nssumhs2022, clean_nssumhs2023)
#year_nums <- seq(2014, 2019)
year_nums <- seq(2014, 2023)
results <- list()
index <- 1
for (year_df in year_dfs)
{
this_df <- year_df %>%
mutate(type = profit_types[OWNERSHP]) %>%
filter(! STATE %in% c("VI", "GU", "PW", "PR", "FM")) %>% #filter out US territories
group_by(STATE, type) %>%
summarize(count = n()) %>%
ungroup() %>%
group_by(STATE) %>%
mutate(percent = count / sum(count)) %>%
ungroup() %>%
pivot_wider(id_cols = STATE, names_from = type, values_from = c("count", "percent")) %>% #pivot long rows to columns
rename_with(~ ifelse(. == "STATE", ., append_number(., year_nums[index])), everything()) #add the year onto the columns to track %>%
# add the dataframe to a list
results[[index]] <- this_df
index <- index + 1
}
`summarise()` has grouped output by 'STATE'. You can override using the `.groups` argument.`summarise()` has grouped output by 'STATE'. You can override using the `.groups` argument.`summarise()` has grouped output by 'STATE'. You can override using the `.groups` argument.`summarise()` has grouped output by 'STATE'. You can override using the `.groups` argument.`summarise()` has grouped output by 'STATE'. You can override using the `.groups` argument.`summarise()` has grouped output by 'STATE'. You can override using the `.groups` argument.`summarise()` has grouped output by 'STATE'. You can override using the `.groups` argument.`summarise()` has grouped output by 'STATE'. You can override using the `.groups` argument.`summarise()` has grouped output by 'STATE'. You can override using the `.groups` argument.`summarise()` has grouped output by 'STATE'. You can override using the `.groups` argument.
Merge the dataframes together
# profit_states_1419 <- results[[1]]
#
# for (index in seq(2, length(results)))
# {
# profit_states_1419 <- left_join(profit_states_1419, results[[index]])
# }
#
# #add columns that calculate the change from 2015 - 2019
# profit_states_1419$change_Forprofit_1519 <- profit_states_1419$count_Forprofit_2019 - profit_states_1419$count_Forprofit_2015
# profit_states_1419$change_Nonprofit_1519 <- profit_states_1419$count_Nonprofit_2019 - profit_states_1419$count_Nonprofit_2015
# profit_states_1419$change_Government_1519 <- profit_states_1419$count_Government_2019 - profit_states_1419$count_Government_2015
profit_states_1423 <- results[[1]]
for (index in seq(2, length(results)))
{
profit_states_1423 <- left_join(profit_states_1423, results[[index]])
}
Joining with `by = join_by(STATE)`Joining with `by = join_by(STATE)`Joining with `by = join_by(STATE)`Joining with `by = join_by(STATE)`Joining with `by = join_by(STATE)`Joining with `by = join_by(STATE)`Joining with `by = join_by(STATE)`Joining with `by = join_by(STATE)`Joining with `by = join_by(STATE)`
#add columns that calculate the change from 2015 - 2019
profit_states_1423$change_Forprofit_1523 <- profit_states_1423$count_Forprofit_2023 - profit_states_1423$count_Forprofit_2015
profit_states_1423$change_Nonprofit_1523 <- profit_states_1423$count_Nonprofit_2023 - profit_states_1423$count_Nonprofit_2015
profit_states_1423$change_Government_1523 <- profit_states_1423$count_Government_2023 - profit_states_1423$count_Government_2015
#merge state abbreviations to state names
state_names <- tolower(c('ALABAMA','ALASKA','AMERICAN SAMOA','ARIZONA','ARKANSAS','CALIFORNIA','COLORADO','CONNECTICUT','DELAWARE','DISTRICT OF COLUMBIA','FLORIDA','GEORGIA','GUAM','HAWAII','IDAHO','ILLINOIS','INDIANA','IOWA','KANSAS','KENTUCKY','LOUISIANA','MAINE','MARYLAND','MASSACHUSETTS','MICHIGAN','MINNESOTA','MISSISSIPPI','MISSOURI','MONTANA','NEBRASKA','NEVADA','NEW HAMPSHIRE','NEW JERSEY','NEW MEXICO','NEW YORK','NORTH CAROLINA','NORTH DAKOTA','NORTHERN MARIANA IS','OHIO','OKLAHOMA','OREGON','PENNSYLVANIA','PUERTO RICO','RHODE ISLAND','SOUTH CAROLINA','SOUTH DAKOTA','TENNESSEE','TEXAS','UTAH','VERMONT','VIRGINIA','VIRGIN ISLANDS','WASHINGTON','WEST VIRGINIA','WISCONSIN','WYOMING'))
state_abbrevs <- c('AL','AK','AS','AZ','AR','CA','CO','CT','DE','DC','FL','GA','GU','HI','ID','IL','IN','IA','KS','KY','LA','ME','MD','MA','MI','MN','MS','MO','MT','NE','NV','NH','NJ','NM','NY','NC','ND','MP','OH','OK','OR','PA','PR','RI','SC','SD','TN','TX','UT','VT','VA','VI','WA','WV','WI','WY')
state_abbrevs_df <- data.frame(state_names, state_abbrevs)
#we may want to switch to using the Freds population data so it is
consistent and we can include from 2013-2024 MERGING DATA TOGETHER TO
INCLUDE COVARIATES:
state_colnames <- c("State_Name", "Y2012", "Y2013", "Y2014", "Y2015", "Y2016", "Y2017", "Y2018", "Y2019", "Y2020")
#statepop_long <- read.csv("../Data/state_health_spending/US_POPULATION20.CSV") %>%
# dplyr::select(state_colnames) %>%
# pivot_longer(cols = state_colnames[-1]) %>%
# filter(State_Name != "") %>%
# mutate(year = gsub("Y", "", name)) %>%
# rename(pop_thousands = value) %>%
# dplyr::select(State_Name, year, pop_thousands)
#statepop_long
state_healthspending_long <- read.csv("../Data/state_health_spending/US_PER_CAPITA20.CSV") %>%
dplyr::select(state_colnames, "Item") %>%
pivot_longer(cols = state_colnames[-1]) %>%
#filter to Personal Health Care, which is total spending
filter(State_Name != "", grepl("Personal Health Care", Item)) %>%
mutate(year = gsub("Y", "", name)) %>%
rename(percapita_health_spending = value, spending_type = Item) %>%
dplyr::select(State_Name, year, percapita_health_spending, spending_type)
state_healthspending_long
question - will medicaid enrollment be correlated with population?
should we divide by that?
state_medicaidenroll_long <- read.csv("../Data/state_health_spending/MEDICAID_ENROLLMENT20.CSV") %>%
dplyr::select(state_colnames) %>%
pivot_longer(cols = state_colnames[-1]) %>%
filter(State_Name != "") %>%
mutate(year = gsub("Y", "", name)) %>%
rename(medicaid_enrollment = value) %>%
dplyr::select(State_Name, year, medicaid_enrollment)
state_medicaidenroll_long
# clean_nsduh_files <- function(folder_path, measure_name)
# {
# #create columns to save the confidence intervals in
# measure_upper <- paste(measure_name, "_ciupper", sep = "")
# measure_lower <- paste(measure_name, "_cilower", sep = "")
#
# #loop through all data in the folder, reformat, and save it
# year_data <- list()
# nsduh_files <- list.files(path = folder_path)
# print(nsduh_files)
# index <- 1
#
# #loop through all the files in the folder
# for (file in nsduh_files)
# {
# this_data <- read.csv(paste(folder_path, file, sep = "")) %>%
# #round the year range (i.e. 2013-2014) up, so we are saving it as the year_end
# separate(year_pair, into = c(NA, "year_end")) %>%
# mutate(year_end = paste("20", year_end, sep = "")) %>%
# rename(!!measure_name := estimate,
# !!measure_lower := ci_lower,
# !!measure_upper := ci_upper) %>%
# dplyr::select(-c(outcome, age_group))
#
# #add it to a list
# year_data[[index]] <- this_data
# index <- index + 1
# }
#
# #append the data from each file into one dataframe and return
# return(bind_rows(year_data))
# }
#
#
# sud_pastyear <- clean_nsduh_files("Data/NSDUH/NSDUH_SUD/", "sud_pastyear")
# needing_notreceiving <- clean_nsduh_files("Data/NSDUH/NSDUH_NeedingNotReceiving/", "needing_tx")
# bingealcohol_pastmonth <- clean_nsduh_files("Data/NSDUH/NSDUH_BingeAlcohol/", "bingealcohol_pastmonth")
# drug_pastmonth <- clean_nsduh_files("Data/NSDUH/NSDUH_IllicitDrugUse/", "drug_pastmonth")
#
# sud_demand_df <- sud_pastyear %>%
# left_join(needing_notreceiving, by= c("state", "year_end")) %>%
# left_join(bingealcohol_pastmonth, by= c("state", "year_end")) %>%
# left_join(drug_pastmonth, by = c("state", "year_end"))
#
# sud_demand_df
Read all NSDUH data from here: https://www.samhsa.gov/data/nsduh/state-reports
library(haven)
nsduh_99_19 <- haven::read_sas("../Data/NSDUH/NSDUH_99_19_state_saes_final.sas7bdat")
nsduh_21_23 <- haven::read_sas("../Data/NSDUH/state_saes_final_2122_22_2223.sas7bdat")
#hitting a hiccup with 2021-2023 NSDUH data - documentation says that the previous years cannot be compared to 2021-2023
# https://www.samhsa.gov/data/sites/default/files/reports/rpt56198/2023-nsduh-puf-data-users-guide.pdf
#nsduh_2020 <- read.table("../Data/NSDUH/NSDUH_2020_Tab.txt", header = TRUE, sep = '\t')
#nsduh_2021 <- read.table("../Data/NSDUH/NSDUH_2021_Tab.txt", header = TRUE, sep = '\t')
#nsduh_2022 <- read.table("../Data/NSDUH/NSDUH_2022_Tab.txt", header = TRUE, sep = '\t')
#nsduh_2023 <- read.table("../Data/NSDUH/NSDUH_2023_Tab.txt", header = TRUE, sep = '\t')
looking for variables which can measure demand but are consistently
available for a longer period of time - alcohol use disorder in the past
year, (ABODALC) cocaine use in the past year, (COCYR) heroin use in the
past year, (HERYR) marijuana use in the past month (MRJMON) - month
chosen over year because it is more frequent and more likely represents
high use / use disorder
(probably won’t include tobacco use because it isnt as often treated
in a specialty facility)
clean_nsduh_data <- function(nsduh_data){
#filter the data to only state reports, and years post-2015
nsduh_data_long <- nsduh_data %>%
separate(pyearnm, into = c("start_year", "end_year"), "-") %>%
filter(area == 2) %>%
filter(outcome %in% nsduh_outcomes) %>%
filter(agegrp == 4) %>% #filter to people above 18 (adults)
mutate(stname_lower = tolower(stname)) %>%
dplyr::select(outname, outcome, start_year, end_year, agegrp, stname,stname_lower, BSAE, low_sae, up_sae)
#pop, est_total, low_total, up_total) #i was previously using est_total but this is the average number of people per state which will be dependent on population
nsduh_data_wide <- nsduh_data_long %>%
select(stname, start_year, end_year, outcome, BSAE) %>%
pivot_wider(id_cols = c(stname, end_year), names_from = outcome, values_from = BSAE, unused_fn = first)
return(nsduh_data_wide)
}
#interested in 4 substance use outcomes
nsduh_outcomes <- c("BNGDRK", "ILLEMMON", "TXNPILAL", "UDPYILAL", "HERYR", "ABODALC", "UDYR5ALC", "COCYR", "HERYR", "MRJMON")
nsduh_data_wide <- clean_nsduh_data(nsduh_99_19)
nsduh_data_wide_21 <- clean_nsduh_data(nsduh_21_23)
Warning: Expected 2 pieces. Missing pieces filled with `NA` in 1064 rows [8345, 8346, 8347, 8348, 8349, 8350, 8351, 8352, 8353, 8354, 8355, 8356, 8357, 8358, 8359, 8360, 8361, 8362, 8363, 8364, ...].
nsduh_data_wide
nsduh_data_wide_21
NA
#this function assumes that statepop_long, state_healthspending_long, and state_medicaidenroll_long are read into memory already
merge_control_vars <- function(nsduh_data, alc_colname)
{
nsduh_data$stname <- trimws(nsduh_data$stname)
state_control_long <- state_healthspending_long %>%
#statepop_long %>%
#inner_join(state_healthspending_long, by = c("State_Name"= "State_Name", "year" = "year")) %>%
inner_join(state_medicaidenroll_long, by = c("State_Name"= "State_Name", "year" = "year")) %>%
#mutate(medicaid_enroll_percapita = medicaid_enrollment / pop_thousands) %>%
#join "demand" measures from NSDUH data
#left_join(nsduh_data, by = c("State_Name" = "stname", "year" = "end_year")) %>%
#changing to right join on 6/12 because we don't have control data for 2021-2023 yet
right_join(nsduh_data, by = c("State_Name" = "stname", "year" = "end_year")) %>%
#join state abbreviations onto dataframe
mutate(state_name_lower = tolower(State_Name)) %>%
left_join(state_abbrevs_df, by = c("state_name_lower" = "state_names")) %>%
dplyr::select(-c(spending_type, state_name_lower)) %>%
rename("binge_drinking" = BNGDRK, "illicit_druguse" = ILLEMMON,
#"needing_tx"= TXNPILAL,
#"sud" = UDPYILAL,
"aud_yr" = {{alc_colname}},
"heroin_yr"=HERYR, "cocaine_yr"=COCYR, "marijuana_month" = MRJMON)
return(state_control_long)
}
state_control_long14 <- merge_control_vars(nsduh_data_wide, "ABODALC")
state_control_long21 <- merge_control_vars(nsduh_data_wide_21, "UDYR5ALC")
state_control_long <- bind_rows(state_control_long14, state_control_long21)
state_control_long <- state_control_long %>% filter(start_year > 2012)
state_control_long
Scale the variables and lag the need variables
#scale to health spending in thousands of dollars
state_control_long$percapita_health_spending_thousands <- state_control_long$percapita_health_spending / 1000
#scale to population in millions
#state_control_long$pop_millions <- state_control_long$pop_thousands / 1000
#change the demand variables to percents
state_control_long$binge_drinking <- state_control_long$binge_drinking * 100
state_control_long$illicit_druguse <- state_control_long$illicit_druguse * 100
#state_control_long$sud <- state_control_long$sud * 100
#state_control_long$needing_tx <- state_control_long$needing_tx * 100
state_control_long$aud_yr <- state_control_long$aud_yr * 100
state_control_long$heroin_yr <- state_control_long$heroin_yr * 100
state_control_long$cocaine_yr <- state_control_long$cocaine_yr * 100
state_control_long$marijuana_month <- state_control_long$marijuana_month * 100
#lag the 4 demand variables , and change them to percentages
state_control_long <- state_control_long %>%
arrange(State_Name, year) %>% # Ensure data is ordered by State_Abbrev and year
group_by(State_Name) %>%
mutate(prev2years_bingedrinking = dplyr::lag(binge_drinking),
prev2years_druguse = dplyr::lag(illicit_druguse),
#prev2years_sud = dplyr::lag(sud),
#prev2years_needingtx = dplyr::lag(needing_tx),
prev2years_aud = dplyr::lag(aud_yr),
prev2years_marijuana = dplyr::lag(marijuana_month),
druguse_calc = (cocaine_yr + heroin_yr)/2, #combine the 2 drug use metrics - average
#BWO 5/22- changing the above metric to divide by 2 for the prevalence of drug use per 100
prev2years_drugusecalc = dplyr::lag(druguse_calc),
prev2years_cocaine = dplyr::lag(cocaine_yr),
prev2years_heroin = dplyr::lag(heroin_yr))
#pivot data to long format
#state_final_df <- profit_states_1419 %>%
state_final_df <- profit_states_1423 %>%
dplyr::select(STATE, contains("count")) %>%
pivot_longer(cols = contains("count")) %>%
separate(name, into = c(NA, "profit_type", "year"), "_") %>%
rename(State_Abbrev = STATE, count_tx = value) %>%
mutate(State_Abbrev = as.character(State_Abbrev), year = as.character(year)) %>%
#join to control variables
left_join(state_control_long, by = c("State_Abbrev" = "state_abbrevs", "year" = "year")) #%>%
#filter(year >= 2016 & year <= 2020) %>%
#mutate(tx_percapita = count_tx / (pop_thousands*1000))
head(state_final_df)
Merging following variables: * race * gender * ethnicity
#read demographic information from 1 year from the WONDER CDC dataset
read_clean_demographic <- function(filepath, year_param)
{
demographic_states <- read.table(filepath, sep = "\t",
fill = TRUE,
header = TRUE) %>%
#after 2020 it is a "Sex" variable instead of "Gender"
rename(any_of(c(Gender = "Sex"))) %>%
filter(!is.na(Population),#filter out unnecessary text at the bottom
Gender != "", #filter to the most granular level of each combination of gender/Race/Ethnicity and then we can aggregate up
Race != "",
Ethnicity != "")
gender_df <- demographic_states %>%
arrange(States) %>%
group_by(States, Gender) %>%
summarize(count = sum(Population)) %>%
#change the count per gender into a percent
mutate(Total = sum(across(where(is.numeric))),
Percent = (count / Total) * 100) %>%
ungroup() %>%
pivot_wider(id_cols = States, names_from = Gender, values_from = Percent, names_glue = "Gender_{Gender}")
race_df <- demographic_states %>%
arrange(States) %>%
group_by(States, Race) %>%
summarize(count = sum(Population)) %>%
#change the count per Race into a percent
mutate(Total = sum(across(where(is.numeric))),
#change the percent from a decimal (i.e. 10% = 0.1) to a percent (i.e 10% = 10) to correspond with other variables' format in df
Percent = (count / Total) * 100) %>%
ungroup() %>%
#replace all spaces in the Race column
mutate(Race = gsub(" ", "", Race)) %>%
#Pivot the race into columns
pivot_wider(id_cols = States, names_from = Race, values_from = Percent, names_glue = "Race_{Race}")
ethnicity_df <- demographic_states %>%
arrange(States) %>%
group_by(States, Ethnicity) %>%
summarize(count = sum(Population)) %>%
#change the count per Ethnicity into a percent
mutate(Total = sum(across(where(is.numeric))),
Percent = (count / Total) * 100) %>%
ungroup() %>%
#replace all spaces in the Ethnicity column
mutate(Ethnicity = gsub(" ", "", Ethnicity)) %>%
#pivot the ethnicity into columns
pivot_wider(id_cols = States, names_from = Ethnicity, values_from = Percent, names_glue = "Ethnicity_{Ethnicity}")
demographics_df <- gender_df %>%
merge(ethnicity_df, by = "States") %>%
merge(race_df, by = "States") %>%
mutate(year = year_param)
return(demographics_df)
}
demographics_2013 <- read_clean_demographic("../Data/StateYear_DemographicInfo/Single-Race Population Estimates 2010-2020 by State and Single-Year Age_2013.txt", 2013)
`summarise()` has grouped output by 'States'. You can override using the `.groups` argument.`summarise()` has grouped output by 'States'. You can override using the `.groups` argument.`summarise()` has grouped output by 'States'. You can override using the `.groups` argument.
demographics_2014 <- read_clean_demographic("../Data/StateYear_DemographicInfo/Single-Race Population Estimates 2010-2020 by State and Single-Year Age_2013.txt", 2014)
`summarise()` has grouped output by 'States'. You can override using the `.groups` argument.`summarise()` has grouped output by 'States'. You can override using the `.groups` argument.`summarise()` has grouped output by 'States'. You can override using the `.groups` argument.
demographics_2015 <- read_clean_demographic("../Data/StateYear_DemographicInfo/Single-Race Population Estimates 2010-2020 by State and Single-Year Age_2013.txt", 2015)
`summarise()` has grouped output by 'States'. You can override using the `.groups` argument.`summarise()` has grouped output by 'States'. You can override using the `.groups` argument.`summarise()` has grouped output by 'States'. You can override using the `.groups` argument.
demographics_2016 <- read_clean_demographic("../Data/StateYear_DemographicInfo/Single-Race Population Estimates 2010-2020 by State and Single-Year Age_2013.txt", 2016)
`summarise()` has grouped output by 'States'. You can override using the `.groups` argument.`summarise()` has grouped output by 'States'. You can override using the `.groups` argument.`summarise()` has grouped output by 'States'. You can override using the `.groups` argument.
demographics_2017 <- read_clean_demographic("../Data/StateYear_DemographicInfo/Single-Race Population Estimates 2010-2020 by State and Single-Year Age_2013.txt", 2017)
`summarise()` has grouped output by 'States'. You can override using the `.groups` argument.`summarise()` has grouped output by 'States'. You can override using the `.groups` argument.`summarise()` has grouped output by 'States'. You can override using the `.groups` argument.
demographics_2018 <- read_clean_demographic("../Data/StateYear_DemographicInfo/Single-Race Population Estimates 2010-2020 by State and Single-Year Age_2013.txt", 2018)
`summarise()` has grouped output by 'States'. You can override using the `.groups` argument.`summarise()` has grouped output by 'States'. You can override using the `.groups` argument.`summarise()` has grouped output by 'States'. You can override using the `.groups` argument.
demographics_2019 <- read_clean_demographic("../Data/StateYear_DemographicInfo/Single-Race Population Estimates 2010-2020 by State and Single-Year Age_2019.txt", 2019)
`summarise()` has grouped output by 'States'. You can override using the `.groups` argument.`summarise()` has grouped output by 'States'. You can override using the `.groups` argument.`summarise()` has grouped output by 'States'. You can override using the `.groups` argument.
demographics_2020 <- read_clean_demographic("../Data/StateYear_DemographicInfo/Single-Race Population Estimates 2020-2022 by State and Single-Year Age_2020.xls", 2020)
`summarise()` has grouped output by 'States'. You can override using the `.groups` argument.`summarise()` has grouped output by 'States'. You can override using the `.groups` argument.`summarise()` has grouped output by 'States'. You can override using the `.groups` argument.
demographics_2021 <- read_clean_demographic("../Data/StateYear_DemographicInfo/Single-Race Population Estimates 2020-2022 by State and Single-Year Age_2021.xls", 2021)
`summarise()` has grouped output by 'States'. You can override using the `.groups` argument.`summarise()` has grouped output by 'States'. You can override using the `.groups` argument.`summarise()` has grouped output by 'States'. You can override using the `.groups` argument.
demographics_2022 <- read_clean_demographic("../Data/StateYear_DemographicInfo/Single-Race Population Estimates 2020-2022 by State and Single-Year Age_2022.xls", 2022)
`summarise()` has grouped output by 'States'. You can override using the `.groups` argument.`summarise()` has grouped output by 'States'. You can override using the `.groups` argument.`summarise()` has grouped output by 'States'. You can override using the `.groups` argument.
state_demographics <- bind_rows(demographics_2013,
demographics_2014,
demographics_2015,
demographics_2016,
demographics_2017,
demographics_2018,
demographics_2019,
demographics_2020,
demographics_2021,
demographics_2022) %>%
mutate(year = as.character(year)) #cast the year column to character
#delete unnecessary dfs
rm(demographics_2013, demographics_2014, demographics_2015, demographics_2016, demographics_2017, demographics_2018, demographics_2019, demographics_2020,demographics_2021, demographics_2022)
Merging insurance variable * insurance
read_clean_insurance <- function(path, year_param)
{
insurance_states <- read.csv(path,
skip=2,
header = TRUE) %>%
filter(!is.na(Total)) %>%
select(-Footnotes) %>%
mutate(year = year_param) %>%
rename_with(~paste0("Insurance_", .x), everything()) %>%
#remove the "Insurance" from year and Location
rename(year = Insurance_year, Location = Insurance_Location)
#some of the columns show "<0.01" - calculate them by subtracting from the other values
insurance_states <- insurance_states %>%
mutate(Insurance_Military = na_if(as.character(Insurance_Military), "<.01")) %>% #change any "<.01" text to na
mutate(Insurance_Military = coalesce(as.numeric(Insurance_Military), 1 - (Insurance_Employer + Insurance_Non.Group + Insurance_Medicaid + Insurance_Medicare + Insurance_Uninsured))) #calculate the remaining percentage
#change the decimals to percents
insurance_states <- insurance_states %>%
mutate(year = as.character(year)) %>% # ensure the year is a character column
mutate_if(is.numeric, ~. * 100)
return(insurance_states)
}
insurance_2013 <- read_clean_insurance("../Data/StateYear_Insurance/raw_data2013.csv", 2013)
insurance_2014 <- read_clean_insurance("../Data/StateYear_Insurance/raw_data2014.csv", 2014)
insurance_2015 <- read_clean_insurance("../Data/StateYear_Insurance/raw_data2015.csv", 2015)
insurance_2016 <- read_clean_insurance("../Data/StateYear_Insurance/raw_data2016.csv", 2016)
insurance_2017 <- read_clean_insurance("../Data/StateYear_Insurance/raw_data2017.csv", 2017)
insurance_2018 <- read_clean_insurance("../Data/StateYear_Insurance/raw_data2018.csv", 2018)
insurance_2019 <- read_clean_insurance("../Data/StateYear_Insurance/raw_data2019.csv", 2019)
#insurance_2020 <- read_clean_insurance("../Data/StateYear_Insurance/raw_data2020.csv", 2020)
insurance_2021 <- read_clean_insurance("../Data/StateYear_Insurance/raw_data2021.csv", 2021)
Warning: There was 1 warning in `mutate()`.
ℹ In argument: `Insurance_Military = coalesce(...)`.
Caused by warning in `list2()`:
! NAs introduced by coercion
insurance_2022 <- read_clean_insurance("../Data/StateYear_Insurance/raw_data2022.csv", 2022)
state_insurance <- bind_rows(insurance_2013, insurance_2014, insurance_2015, insurance_2016, insurance_2017, insurance_2018, insurance_2019,
#insurance_2020,
insurance_2021, insurance_2022) %>%
mutate(year = as.character(year))
#delete unnecessary dfs
rm(insurance_2013, insurance_2014, insurance_2015, insurance_2016, insurance_2017, insurance_2018, insurance_2019, #insurance_2020,
insurance_2021, insurance_2022)
Merging poverty and unemployment variables
library(janitor) #use to overwrite row names
library(tibble)
library(readxl)
freds_name_mapping <- read_excel("../Data/StateYear_Income_Unemployed/State_Population_Unemployment_Income.xlsx", sheet=2)
#create a named vector of the values from the name mapping
state_names <- freds_name_mapping$State_Parsed
names(state_names) <- freds_name_mapping$`Series ID:`
value_names <- freds_name_mapping$`Title:`
names(value_names) <- freds_name_mapping$`Series ID:`
freds_df_unformatted <- read_excel("../Data/StateYear_Income_Unemployed/State_Population_Unemployment_Income.xlsx", sheet=3)
freds_df <- freds_df_unformatted %>%
#switch the rows and the columns so the values are in the rows and columns are years
t() %>%
#cast to dataframe
as.data.frame() %>%
#move the first row to be the header
janitor::row_to_names(row_number = 1) %>%
#rename the row names to "freds_colname"
tibble::rownames_to_column("freds_colname") %>%
mutate(val = value_names[freds_colname]) %>%
#mark which variables we are looking at
separate(val, into = c("variable_measure", "state_name"), sep = " in ") %>%
#remove "the" from DC name
mutate(state_name = ifelse(state_name == "the District of Columbia", "District of Columbia", state_name)) %>%
#shorten variable measure names
mutate(variable_measure = ifelse(variable_measure == "Resident Population", "Population",
ifelse(variable_measure == "Unemployment Rate", "Unemployment",
ifelse(variable_measure == "Real Median Household Income", "Income", "MISSING")))) %>%
#remove month/date from year names - unnecessary
rename("2013" = "2013-01-01",
"2014" = "2014-01-01",
"2015" = "2015-01-01",
"2016" = "2016-01-01",
"2017" = "2017-01-01",
"2018" = "2018-01-01",
"2019" = "2019-01-01",
"2020" = "2020-01-01",
"2021" = "2021-01-01",
"2022" = "2022-01-01",
"2023" = "2023-01-01") %>%
#change the years from the columns to a row indicator - data is now in long format with one row per state-year-measurement
pivot_longer(cols = c("2013", "2014", "2015", "2016", "2017", "2018", "2020", "2019", "2022", "2023")) %>%
rename("year" = name) %>%
#pivot the individual measures into columns so we have only one row per state-year
pivot_wider(id_cols = c(state_name, year), values_from = value, names_from = variable_measure) %>%
#cast numeric variables to numeric
mutate(year = as.character(year), Population = as.numeric(Population), Unemployment = as.numeric(Unemployment), Income = as.numeric(Income))
state_final_df <- state_final_df %>%
#join demographic information
left_join(state_demographics, by = c("State_Name"="States", "year"="year")) %>%
#join insurance information
left_join(state_insurance, by = c("State_Name"="Location", "year"="year")) %>%
#join the population, unemployment, and income information
left_join(freds_df, by=c("State_Name"="state_name", "year"="year"))
Error: object 'state_final_df' not found
These are available starting at 2013-2014: alcohol use disorder in
the past year, cocaine use in the past year, heroin use in the past
year, marijuana use in the past month (probably won’t include tobacco
use because it isnt as often treated in a specialty facility)
# state_forprofit <- state_final_df %>%
# arrange(State_Abbrev, year) %>% # Ensure data is ordered by State_Abbrev and year
# group_by(State_Abbrev) %>%
# filter(profit_type == "Forprofit", !is.na(prev2years_drugusecalc)) #2014 does not have this data
#
# state_nonprofit <- state_final_df %>%
# arrange(State_Abbrev, year) %>% # Ensure data is ordered by State_Abbrev and year
# group_by(State_Abbrev) %>%
# filter(profit_type == "Nonprofit", !is.na(prev2years_drugusecalc))
#
# state_govt <- state_final_df %>%
# arrange(State_Abbrev, year) %>% # Ensure data is ordered by State_Abbrev and year
# group_by(State_Abbrev) %>%
# filter(profit_type == "Government", !is.na(prev2years_drugusecalc))
#
#
# state_totals <- state_final_df %>%
# filter(!is.na(prev2years_drugusecalc)) %>% #filter out rows we don't want first
# group_by(State_Abbrev, year) %>%
# mutate(count_tx_total = sum(count_tx, na.rm = TRUE)) %>% #calculate the total number of treatment centers per year
# select(-c(count_tx, profit_type)) %>% #remove the columns that only applied to specific treatment center counts
# ungroup() %>%
# rename(count_tx = count_tx_total) %>%
# distinct(State_Abbrev, year, count_tx, .keep_all = TRUE)# get rid of the duplicate rows of control variables for each profit status
#
# write.csv(state_forprofit, "Data/CleanData/Forprofit_finaldata.csv", row.names = FALSE)
# write.csv(state_nonprofit, "Data/CleanData/Nonprofit_finaldata.csv", row.names = FALSE)
# write.csv(state_govt, "Data/CleanData/Government_finaldata.csv", row.names = FALSE)
# write.csv(state_totals, "Data/CleanData/Totals_finaldata.csv", row.names = FALSE)
state_final_df <- state_final_df %>%
pivot_wider(id_cols = c(State_Abbrev, year, "State_Name", "pop_millions", "percapita_health_spending_thousands", "medicaid_enroll_percapita", "prev2years_drugusecalc", "prev2years_aud", "prev2years_marijuana", "Gender_Male", "Ethnicity_HispanicorLatino", "Race_White", "Insurance_Uninsured", "Unemployment", "Income"), #keep all variables we will need for the model
names_from = profit_type, values_from = count_tx) %>%
#calculate the sum of all profit types
rowwise() %>%
mutate(count_tx_total = sum(Forprofit, Nonprofit, Government, na.rm = TRUE)) %>%
#filter only to data that will allow the lagging
filter(year >= 2015) %>%
#replace the nan in Government with 0
mutate(Government = ifelse(is.na(Government), 0, Government))
drugoverdose_df <- read.csv("../Data/CDC_DrugOverdoseDeaths.csv")
#format the data
drugoverdose_df <- drugoverdose_df %>%
arrange(STATE, YEAR) %>%
mutate(YEAR = as.character(YEAR),
overdose_rate_lag = lag(RATE)) %>%
rename(overdose_rate = RATE) %>%
select(STATE, YEAR, overdose_rate, overdose_rate_lag)
#merge the overdose data onto the final df
state_final_df <- state_final_df %>%
left_join(drugoverdose_df, by = c('year'='YEAR', 'State_Abbrev'='STATE'))
write.csv(state_final_df, "../Data/CleanData/Allprofit_finaldata_6.12.25.csv", row.names = FALSE)
As of 6/12/25 - creating a new dataset that separates out the
OTPs:
nssats2014 %>% filter(OTP==1)
OTP_results <- list()
OTP_index <- 1
for (year_df in year_dfs)
{
this_df <- year_df %>%
mutate(type = profit_types[OWNERSHP],
OTP_binary = ifelse(OTP == 1, "OTP", "Not_OTP")) %>%
filter(! STATE %in% c("VI", "GU", "PW", "PR", "FM")) %>% #filter out US territories
group_by(STATE, OTP_binary, type) %>%
summarize(count = n()) %>%
mutate(OTP_profit_group = paste(type,OTP_binary, sep = "_")) %>%
ungroup() %>%
group_by(STATE) %>%
mutate(percent = count / sum(count)) %>%
ungroup() %>%
pivot_wider(id_cols = STATE, names_from = OTP_profit_group, values_from = c("count", "percent")) %>% #pivot long rows to columns
rename_with(~ ifelse(. == "STATE", ., append_number(., year_nums[OTP_index])), everything()) #add the year onto the columns to track %>%
# add the dataframe to a list
OTP_results[[OTP_index]] <- this_df
OTP_index <- OTP_index + 1
}
`summarise()` has grouped output by 'STATE', 'OTP_binary'. You can override using the `.groups` argument.`summarise()` has grouped output by 'STATE', 'OTP_binary'. You can override using the `.groups` argument.`summarise()` has grouped output by 'STATE', 'OTP_binary'. You can override using the `.groups` argument.`summarise()` has grouped output by 'STATE', 'OTP_binary'. You can override using the `.groups` argument.`summarise()` has grouped output by 'STATE', 'OTP_binary'. You can override using the `.groups` argument.`summarise()` has grouped output by 'STATE', 'OTP_binary'. You can override using the `.groups` argument.`summarise()` has grouped output by 'STATE', 'OTP_binary'. You can override using the `.groups` argument.`summarise()` has grouped output by 'STATE', 'OTP_binary'. You can override using the `.groups` argument.`summarise()` has grouped output by 'STATE', 'OTP_binary'. You can override using the `.groups` argument.`summarise()` has grouped output by 'STATE', 'OTP_binary'. You can override using the `.groups` argument.
profit_states_OTP_1423 <- OTP_results[[1]]
for (OTP_index in seq(2, length(OTP_results)))
{
profit_states_OTP_1423 <- left_join(profit_states_OTP_1423, OTP_results[[OTP_index]])
}
Joining with `by = join_by(STATE)`Joining with `by = join_by(STATE)`Joining with `by = join_by(STATE)`Joining with `by = join_by(STATE)`Joining with `by = join_by(STATE)`Joining with `by = join_by(STATE)`Joining with `by = join_by(STATE)`Joining with `by = join_by(STATE)`Joining with `by = join_by(STATE)`
profit_states_OTP_1423
LS0tCnRpdGxlOiAiU0FNU0hBIE5TU0FUUyBEYXRhIENsZWFuaW5nIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgoKCmBgYHtyfQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHlyKQpgYGAKCgpgYGB7cn0KI2NvdWxkIGkgbG9vayBhdCBQUklNUEFZIGFuZCBITFRISU5TIGNvbHVtbnMgdG8gaW52ZXN0aWdhdGUgbW9yYWwgaGF6YXJkIG9uIHRoZSBwYXJ0IG9mIHRyZWF0bWVudCBjZW50ZXJzIGZvciBwYXRpZW50cyB3aXRoIGNlcnRhaW4gaW5zdXJhbmNlL3BheW1lbnQgY2hhcmFjdGVyaXN0aWNzIChsb25nZXIgc3RheXMpPwoKYWRtaXNzaW9uX2NvbHMgPC0gYygiQ0FTRUlEIiwgIlBSRUciLCAiU1RGSVBTIiwgICMgc3RhdGUgSUQgCiAgICAgICAgICAgICAgICAgICAgIlNFUlZJQ0VTIiwgICMgdHlwZSBvZiB0cmVhdG1lbnQgLyBzZXJ2aWNlIHNldHRpbmcKICAgICAgICAgICAgICAgICAgICAiUFNPVVJDRSIsICAjIG1ldGhvZCBvZiByZWZlcnJhbCB0byB0cmVhdG1lbnQKICAgICAgICAgICAgICAgICAgICAiTk9QUklPUiIsICMgcHJpb3IgYWRtaXNzaW9ucyB0byB0cmVhdG1lbnQKICAgICAgICAgICAgICAgICAgICAiU1VCMSIsICJST1VURTEiLCAiRlJFUTEiLCAiRlJTVFVTRTEiLCAjIGNoYXJhY3RlcmlzdGljcyBvZiB0aGVpciBwcmltYXJ5IHN1YnN0YW5jZSwgbWV0aG9kIGFuZCBmcmVxdWVuY3kgb2YgdXNlICAoY291bGQgYWxzbyBpbmNsdWRlIHNlY29uZCBzdWJzdGFuY2VzKQogICAgICAgICAgICAgICAgICAgICJITFRISU5TIiwgIlBSSU1QQVkiLCAjIHBheW1lbnQgZGV0YWlscyBvZiBpbnRlcmVzdAogICAgICAgICAgICAgICAgICAgICJSRUFTT04iLCAjIHJlYXNvbiBmb3IgZGlzY2hhcmdlCiAgICAgICAgICAgICAgICAgICAgIkxPUyIgI2xlbmd0aCBvZiBzdGF5IAogICAgICAgICAgICAgICAgICAgICkKCmBgYAoKYGBge3J9Cm5zc3VtaHMyMDIxIDwtIHJlYWQuY3N2KCIuLi9EYXRhL05TVU1IU1MvTlNVTUhTU18yMDIxX1BVRl9DU1YuY3N2IikKbnNzdW1oczIwMjIgPC0gcmVhZC5jc3YoIi4uL0RhdGEvTlNVTUhTUy9OU1VNSFNTXzIwMjJfUFVGX0NTVi5jc3YiKQpuc3N1bWhzMjAyMyA8LSByZWFkLmNzdigiLi4vRGF0YS9OU1VNSFNTL05TVU1IU1NfMjAyM19QVUZfQ1NWLmNzdiIpCgpgYGAKCmBgYHtyfQpoZWFkKG5zc3VtaHMyMDIxKQpgYGAKCmBgYHtyfQp0YWJsZShuc3N1bWhzMjAyMSRPV05FUlNIUCkgI00gYW5kIEwgYXJlIG1pc3NpbmcgZGF0YSAKdGFibGUobnNzdW1oczIwMjEkVFJFQVRNVF9TVSkgI2FjY29yZGluZyB0byBkb2N1bWVudGF0aW9uLCB0aGUgVFJFQVRNVF9TVSBxdWVzdGlvbiBhc2tzIHdoZXRoZXIgdGhleSBvZmZlciBTdWJzdGFuY2UgdXNlIHRyZWF0bWVudAojd2UgY2FuIGZpbHRlciB0byB3aGVyZSB0aGUgYW5zd2VyIGlzICIxIiBmb3IgeWVzIChub3QgMCBmb3Igbm8sIEwgZm9yIGxvZ2ljYWwgc2tpcCwgbm9yIE0gZm9yIG1pc3NpbmcpIApgYGAKYGBge3IgY2xlYW4gTlNTVU1IUyBkYXRhIHNvIGl0IGNhbiBiZSBjb25jYXRlbmF0ZWQgd2l0aCBOU1NBVFMgZGF0YX0KCmNsZWFuX25zc3VtaHMgPC0gZnVuY3Rpb24oZGYpewogIGNsZWFuX2RmIDwtIGRmICU+JSAKICAgICNmaWx0ZXIgdG8gd2hlcmUgVFJFQVRNVF9TVSBpcyAxICwgbWVhbmluZyB0aGV5IHByb3ZpZGUgc3Vic3RhbmNlIHVzZSB0cmVhdG1lbnQKICBmaWx0ZXIoVFJFQVRNVF9TVSA9PSAxKSAlPiUKICAgICNyZW5hbWUgTE9DQVRJT05TVEFURSB0byBTVEFURSB0byBtYXRjaCBOU1NBVFMKICByZW5hbWUoU1RBVEUgPSBMT0NBVElPTlNUQVRFKSAlPiUKICAgICNyZXBsYWNlIE0gYW5kIEwgaW4gb3duZXJzaGlwIGNvbHVtbiB3aXRoIG1pc3NpbmcgKG5hKQogICNtdXRhdGUoT1dORVJTSFAgPSBpZmVsc2UoaXMubmEoT1dORVJTSFApLCBOQSwgT1dORVJTSFApKSAlPiUKICAgICNhbHRlcm5hdGl2ZWx5IGNhbiBmaWx0ZXIgb3V0IG1pc3Npbmcgb3duZXJzaGlwIGNvbHVtbnMKICAgIGZpbHRlcigoT1dORVJTSFAgIT0gIk0iKSAmIChPV05FUlNIUCAhPSAiTCIpKSAlPiUKICAgICNjYXN0IG93bmVyc2hpcCB0byBpbnRlZ2VyCiAgICBtdXRhdGUoT1dORVJTSFAgPSBhcy5pbnRlZ2VyKE9XTkVSU0hQKSkKICAKICByZXR1cm4oY2xlYW5fZGYpCn0KY2xlYW5fbnNzdW1oczIwMjEgPC0gY2xlYW5fbnNzdW1ocyhuc3N1bWhzMjAyMSkKY2xlYW5fbnNzdW1oczIwMjIgPC0gY2xlYW5fbnNzdW1ocyhuc3N1bWhzMjAyMikKY2xlYW5fbnNzdW1oczIwMjMgPC0gY2xlYW5fbnNzdW1ocyhuc3N1bWhzMjAyMykKCmBgYAoKCgoKYGBge3J9CiNuc3NhdHMyMDA5IDwtIHJlYWQuY3N2KCJOLVNTQVRTLTIwMDktRFMwMDAxLWJuZGwtZGF0YS10c3YvTi1TU0FUUy0yMDA5LURTMDAwMS1kYXRhL04tU1NBVFMtMjAwOS1EUzAwMDEtZGF0YS1leGNlbC5jc3YiKQpuc3NhdHMyMDE0IDwtIHJlYWQuY3N2KCIuLi9EYXRhL05TU0FUUy9OLVNTQVRTLTIwMTQtRFMwMDAxLWJuZGwtZGF0YS10c3YvTi1TU0FUUy0yMDE0LURTMDAwMS1kYXRhL04tU1NBVFMtMjAxNC1EUzAwMDEtZGF0YS1leGNlbC5jc3YiKQpuc3NhdHMyMDE1IDwtIHJlYWQuY3N2KCIuLi9EYXRhL05TU0FUUy9OLVNTQVRTLTIwMTUtRFMwMDAxLWJuZGwtZGF0YS10c3YvTi1TU0FUUy0yMDE1LURTMDAwMS1kYXRhL04tU1NBVFMtMjAxNS1EUzAwMDEtZGF0YS1leGNlbC5jc3YiKQpuc3NhdHMyMDE2IDwtIHJlYWQuY3N2KCIuLi9EYXRhL05TU0FUUy9OU1NBVFNQVUZfMjAxNi5jc3YiKQpuc3NhdHMyMDE3IDwtIHJlYWQuY3N2KCIuLi9EYXRhL05TU0FUUy9OU1NBVFNfUFVGXzIwMTdfQ1NWLmNzdiIpCm5zc2F0czIwMTggPC0gcmVhZC5jc3YoIi4uL0RhdGEvTlNTQVRTL05TU0FUU19QVUZfMjAxOF9DU1YuY3N2IikKbnNzYXRzMjAxOSA8LSByZWFkLmNzdigiLi4vRGF0YS9OU1NBVFMvTlNTQVRTX1BVRl8yMDE5X0NTVi5jc3YiKQpuc3NhdHMyMDIwIDwtIHJlYWQuY3N2KCIuLi9EYXRhL05TU0FUUy9OU1NBVFNfUFVGXzIwMjBfQ1NWLmNzdiIpCmhlYWQobnNzYXRzMjAxNSkKYGBgCgpEYXRhIGNsZWFuaW5nIG9uIGFsbCBkZnMgCmBgYHtyfQoKcHJvZml0X3R5cGVzIDwtIGMoIkZvcnByb2ZpdCIsICJOb25wcm9maXQiLCAiR292ZXJubWVudCIsICJHb3Zlcm5tZW50IiwgIkdvdmVybm1lbnQiLCAiR292ZXJubWVudCIpCgojIEZ1bmN0aW9uIHRvIGFwcGVuZCBhIG51bWJlciB0byBjb2x1bW4gbmFtZXMgKGZyb20gQ2hhdEdQVCkKYXBwZW5kX251bWJlciA8LSBmdW5jdGlvbihuYW1lLCBudW0pIHsKICBwYXN0ZShuYW1lLCBudW0sIHNlcCA9ICJfIikKfQoKI3llYXJfZGZzIDwtIGxpc3QobnNzYXRzMjAxNCwgbnNzYXRzMjAxNSwgbnNzYXRzMjAxNiwgbnNzYXRzMjAxNywgbnNzYXRzMjAxOCwgbnNzYXRzMjAxOSkjLCBuc3NhdHMyMDIwKQp5ZWFyX2RmcyA8LSBsaXN0KG5zc2F0czIwMTQsIG5zc2F0czIwMTUsIG5zc2F0czIwMTYsIG5zc2F0czIwMTcsIG5zc2F0czIwMTgsIG5zc2F0czIwMTksIG5zc2F0czIwMjAsIAogICAgICAgICAgICAgICAgIGNsZWFuX25zc3VtaHMyMDIxLCBjbGVhbl9uc3N1bWhzMjAyMiwgY2xlYW5fbnNzdW1oczIwMjMpCgojeWVhcl9udW1zIDwtIHNlcSgyMDE0LCAyMDE5KQp5ZWFyX251bXMgPC0gc2VxKDIwMTQsIDIwMjMpCgpyZXN1bHRzIDwtIGxpc3QoKQppbmRleCA8LSAxCmZvciAoeWVhcl9kZiBpbiB5ZWFyX2RmcykKewogIHRoaXNfZGYgPC0geWVhcl9kZiAlPiUgCiAgICBtdXRhdGUodHlwZSA9IHByb2ZpdF90eXBlc1tPV05FUlNIUF0pICU+JQogICAgZmlsdGVyKCEgU1RBVEUgJWluJSBjKCJWSSIsICJHVSIsICJQVyIsICJQUiIsICJGTSIpKSAlPiUgI2ZpbHRlciBvdXQgVVMgdGVycml0b3JpZXMKICAgIGdyb3VwX2J5KFNUQVRFLCB0eXBlKSAlPiUgCiAgICBzdW1tYXJpemUoY291bnQgPSBuKCkpICU+JQogICAgdW5ncm91cCgpICU+JQogICAgZ3JvdXBfYnkoU1RBVEUpICU+JQogICAgbXV0YXRlKHBlcmNlbnQgPSBjb3VudCAvIHN1bShjb3VudCkpICU+JSAKICAgIHVuZ3JvdXAoKSAlPiUKICAgIHBpdm90X3dpZGVyKGlkX2NvbHMgPSBTVEFURSwgbmFtZXNfZnJvbSA9IHR5cGUsIHZhbHVlc19mcm9tID0gYygiY291bnQiLCAicGVyY2VudCIpKSAlPiUgI3Bpdm90IGxvbmcgcm93cyB0byBjb2x1bW5zCiAgICByZW5hbWVfd2l0aCh+IGlmZWxzZSguID09ICJTVEFURSIsIC4sIGFwcGVuZF9udW1iZXIoLiwgeWVhcl9udW1zW2luZGV4XSkpLCBldmVyeXRoaW5nKCkpICAjYWRkIHRoZSB5ZWFyIG9udG8gdGhlIGNvbHVtbnMgdG8gdHJhY2sgJT4lCiAgCgogICMgYWRkIHRoZSBkYXRhZnJhbWUgdG8gYSBsaXN0IAogIHJlc3VsdHNbW2luZGV4XV0gPC0gdGhpc19kZgogIGluZGV4IDwtIGluZGV4ICsgMQogIAp9CgpgYGAKCgpNZXJnZSB0aGUgZGF0YWZyYW1lcyB0b2dldGhlcgpgYGB7cn0KCiMgcHJvZml0X3N0YXRlc18xNDE5IDwtIHJlc3VsdHNbWzFdXQojIAojIGZvciAoaW5kZXggaW4gc2VxKDIsIGxlbmd0aChyZXN1bHRzKSkpCiMgewojICAgcHJvZml0X3N0YXRlc18xNDE5IDwtIGxlZnRfam9pbihwcm9maXRfc3RhdGVzXzE0MTksIHJlc3VsdHNbW2luZGV4XV0pCiMgfQojIAojICNhZGQgY29sdW1ucyB0aGF0IGNhbGN1bGF0ZSB0aGUgY2hhbmdlIGZyb20gMjAxNSAtIDIwMTkgCiMgcHJvZml0X3N0YXRlc18xNDE5JGNoYW5nZV9Gb3Jwcm9maXRfMTUxOSA8LSBwcm9maXRfc3RhdGVzXzE0MTkkY291bnRfRm9ycHJvZml0XzIwMTkgLSBwcm9maXRfc3RhdGVzXzE0MTkkY291bnRfRm9ycHJvZml0XzIwMTUKIyBwcm9maXRfc3RhdGVzXzE0MTkkY2hhbmdlX05vbnByb2ZpdF8xNTE5IDwtIHByb2ZpdF9zdGF0ZXNfMTQxOSRjb3VudF9Ob25wcm9maXRfMjAxOSAtIHByb2ZpdF9zdGF0ZXNfMTQxOSRjb3VudF9Ob25wcm9maXRfMjAxNQojIHByb2ZpdF9zdGF0ZXNfMTQxOSRjaGFuZ2VfR292ZXJubWVudF8xNTE5IDwtIHByb2ZpdF9zdGF0ZXNfMTQxOSRjb3VudF9Hb3Zlcm5tZW50XzIwMTkgLSBwcm9maXRfc3RhdGVzXzE0MTkkY291bnRfR292ZXJubWVudF8yMDE1Cgpwcm9maXRfc3RhdGVzXzE0MjMgPC0gcmVzdWx0c1tbMV1dCgpmb3IgKGluZGV4IGluIHNlcSgyLCBsZW5ndGgocmVzdWx0cykpKQp7CiAgcHJvZml0X3N0YXRlc18xNDIzIDwtIGxlZnRfam9pbihwcm9maXRfc3RhdGVzXzE0MjMsIHJlc3VsdHNbW2luZGV4XV0pCn0KCiNhZGQgY29sdW1ucyB0aGF0IGNhbGN1bGF0ZSB0aGUgY2hhbmdlIGZyb20gMjAxNSAtIDIwMTkgCnByb2ZpdF9zdGF0ZXNfMTQyMyRjaGFuZ2VfRm9ycHJvZml0XzE1MjMgPC0gcHJvZml0X3N0YXRlc18xNDIzJGNvdW50X0ZvcnByb2ZpdF8yMDIzIC0gcHJvZml0X3N0YXRlc18xNDIzJGNvdW50X0ZvcnByb2ZpdF8yMDE1CnByb2ZpdF9zdGF0ZXNfMTQyMyRjaGFuZ2VfTm9ucHJvZml0XzE1MjMgPC0gcHJvZml0X3N0YXRlc18xNDIzJGNvdW50X05vbnByb2ZpdF8yMDIzIC0gcHJvZml0X3N0YXRlc18xNDIzJGNvdW50X05vbnByb2ZpdF8yMDE1CnByb2ZpdF9zdGF0ZXNfMTQyMyRjaGFuZ2VfR292ZXJubWVudF8xNTIzIDwtIHByb2ZpdF9zdGF0ZXNfMTQyMyRjb3VudF9Hb3Zlcm5tZW50XzIwMjMgLSBwcm9maXRfc3RhdGVzXzE0MjMkY291bnRfR292ZXJubWVudF8yMDE1CgoKYGBgCgoKCmBgYHtyfQojbWVyZ2Ugc3RhdGUgYWJicmV2aWF0aW9ucyB0byBzdGF0ZSBuYW1lcwpzdGF0ZV9uYW1lcyA8LSB0b2xvd2VyKGMoJ0FMQUJBTUEnLCdBTEFTS0EnLCdBTUVSSUNBTiBTQU1PQScsJ0FSSVpPTkEnLCdBUktBTlNBUycsJ0NBTElGT1JOSUEnLCdDT0xPUkFETycsJ0NPTk5FQ1RJQ1VUJywnREVMQVdBUkUnLCdESVNUUklDVCBPRiBDT0xVTUJJQScsJ0ZMT1JJREEnLCdHRU9SR0lBJywnR1VBTScsJ0hBV0FJSScsJ0lEQUhPJywnSUxMSU5PSVMnLCdJTkRJQU5BJywnSU9XQScsJ0tBTlNBUycsJ0tFTlRVQ0tZJywnTE9VSVNJQU5BJywnTUFJTkUnLCdNQVJZTEFORCcsJ01BU1NBQ0hVU0VUVFMnLCdNSUNISUdBTicsJ01JTk5FU09UQScsJ01JU1NJU1NJUFBJJywnTUlTU09VUkknLCdNT05UQU5BJywnTkVCUkFTS0EnLCdORVZBREEnLCdORVcgSEFNUFNISVJFJywnTkVXIEpFUlNFWScsJ05FVyBNRVhJQ08nLCdORVcgWU9SSycsJ05PUlRIIENBUk9MSU5BJywnTk9SVEggREFLT1RBJywnTk9SVEhFUk4gTUFSSUFOQSBJUycsJ09ISU8nLCdPS0xBSE9NQScsJ09SRUdPTicsJ1BFTk5TWUxWQU5JQScsJ1BVRVJUTyBSSUNPJywnUkhPREUgSVNMQU5EJywnU09VVEggQ0FST0xJTkEnLCdTT1VUSCBEQUtPVEEnLCdURU5ORVNTRUUnLCdURVhBUycsJ1VUQUgnLCdWRVJNT05UJywnVklSR0lOSUEnLCdWSVJHSU4gSVNMQU5EUycsJ1dBU0hJTkdUT04nLCdXRVNUIFZJUkdJTklBJywnV0lTQ09OU0lOJywnV1lPTUlORycpKQpzdGF0ZV9hYmJyZXZzIDwtIGMoJ0FMJywnQUsnLCdBUycsJ0FaJywnQVInLCdDQScsJ0NPJywnQ1QnLCdERScsJ0RDJywnRkwnLCdHQScsJ0dVJywnSEknLCdJRCcsJ0lMJywnSU4nLCdJQScsJ0tTJywnS1knLCdMQScsJ01FJywnTUQnLCdNQScsJ01JJywnTU4nLCdNUycsJ01PJywnTVQnLCdORScsJ05WJywnTkgnLCdOSicsJ05NJywnTlknLCdOQycsJ05EJywnTVAnLCdPSCcsJ09LJywnT1InLCdQQScsJ1BSJywnUkknLCdTQycsJ1NEJywnVE4nLCdUWCcsJ1VUJywnVlQnLCdWQScsJ1ZJJywnV0EnLCdXVicsJ1dJJywnV1knKQpzdGF0ZV9hYmJyZXZzX2RmIDwtIGRhdGEuZnJhbWUoc3RhdGVfbmFtZXMsIHN0YXRlX2FiYnJldnMpCmBgYAoKCgojd2UgbWF5IHdhbnQgdG8gc3dpdGNoIHRvIHVzaW5nIHRoZSBGcmVkcyBwb3B1bGF0aW9uIGRhdGEgc28gaXQgaXMgY29uc2lzdGVudCBhbmQgd2UgY2FuIGluY2x1ZGUgZnJvbSAyMDEzLTIwMjQKTUVSR0lORyBEQVRBIFRPR0VUSEVSIFRPIElOQ0xVREUgQ09WQVJJQVRFUzoKYGBge3IgcmVhZCBhbmQgY2xlYW4gQ01TIHBvcHVsYXRpb24gZGF0YSB9CnN0YXRlX2NvbG5hbWVzIDwtIGMoIlN0YXRlX05hbWUiLCAiWTIwMTIiLCAiWTIwMTMiLCAiWTIwMTQiLCAiWTIwMTUiLCAiWTIwMTYiLCAiWTIwMTciLCAiWTIwMTgiLCAiWTIwMTkiLCAiWTIwMjAiKQoKI3N0YXRlcG9wX2xvbmcgPC0gcmVhZC5jc3YoIi4uL0RhdGEvc3RhdGVfaGVhbHRoX3NwZW5kaW5nL1VTX1BPUFVMQVRJT04yMC5DU1YiKSAlPiUgCiMgIGRwbHlyOjpzZWxlY3Qoc3RhdGVfY29sbmFtZXMpICU+JQojICBwaXZvdF9sb25nZXIoY29scyA9IHN0YXRlX2NvbG5hbWVzWy0xXSkgJT4lIAojICBmaWx0ZXIoU3RhdGVfTmFtZSAhPSAiIikgJT4lCiMgIG11dGF0ZSh5ZWFyID0gZ3N1YigiWSIsICIiLCBuYW1lKSkgJT4lCiMgIHJlbmFtZShwb3BfdGhvdXNhbmRzID0gdmFsdWUpICU+JQojICBkcGx5cjo6c2VsZWN0KFN0YXRlX05hbWUsIHllYXIsIHBvcF90aG91c2FuZHMpCgojc3RhdGVwb3BfbG9uZwpgYGAKCmBgYHtyIHJlYWQgYW5kIGNsZWFuIENNUyBwZXIgY2FwaXRhIGhlYWx0aGNhcmUgc3BlbmRpbmd9CnN0YXRlX2hlYWx0aHNwZW5kaW5nX2xvbmcgPC0gcmVhZC5jc3YoIi4uL0RhdGEvc3RhdGVfaGVhbHRoX3NwZW5kaW5nL1VTX1BFUl9DQVBJVEEyMC5DU1YiKSAlPiUKICBkcGx5cjo6c2VsZWN0KHN0YXRlX2NvbG5hbWVzLCAiSXRlbSIpICU+JQogIHBpdm90X2xvbmdlcihjb2xzID0gc3RhdGVfY29sbmFtZXNbLTFdKSAlPiUgCiAgI2ZpbHRlciB0byBQZXJzb25hbCBIZWFsdGggQ2FyZSwgd2hpY2ggaXMgdG90YWwgc3BlbmRpbmcgCiAgZmlsdGVyKFN0YXRlX05hbWUgIT0gIiIsIGdyZXBsKCJQZXJzb25hbCBIZWFsdGggQ2FyZSIsIEl0ZW0pKSAlPiUKICBtdXRhdGUoeWVhciA9IGdzdWIoIlkiLCAiIiwgbmFtZSkpICU+JQogIHJlbmFtZShwZXJjYXBpdGFfaGVhbHRoX3NwZW5kaW5nID0gdmFsdWUsIHNwZW5kaW5nX3R5cGUgPSBJdGVtKSAlPiUKICBkcGx5cjo6c2VsZWN0KFN0YXRlX05hbWUsIHllYXIsIHBlcmNhcGl0YV9oZWFsdGhfc3BlbmRpbmcsIHNwZW5kaW5nX3R5cGUpCgpzdGF0ZV9oZWFsdGhzcGVuZGluZ19sb25nIApgYGAKCgoKcXVlc3Rpb24gLSB3aWxsIG1lZGljYWlkIGVucm9sbG1lbnQgYmUgY29ycmVsYXRlZCB3aXRoIHBvcHVsYXRpb24/IHNob3VsZCB3ZSBkaXZpZGUgYnkgdGhhdD8KYGBge3IgcmVhZCBhbmQgY2xlYW4gQ01TIG1lZGljYWlkIGVucm9sbG1lbnQgZGF0YX0KCnN0YXRlX21lZGljYWlkZW5yb2xsX2xvbmcgPC0gcmVhZC5jc3YoIi4uL0RhdGEvc3RhdGVfaGVhbHRoX3NwZW5kaW5nL01FRElDQUlEX0VOUk9MTE1FTlQyMC5DU1YiKSAlPiUKICAgZHBseXI6OnNlbGVjdChzdGF0ZV9jb2xuYW1lcykgJT4lCiAgIHBpdm90X2xvbmdlcihjb2xzID0gc3RhdGVfY29sbmFtZXNbLTFdKSAlPiUgCiAgIGZpbHRlcihTdGF0ZV9OYW1lICE9ICIiKSAlPiUKICAgbXV0YXRlKHllYXIgPSBnc3ViKCJZIiwgIiIsIG5hbWUpKSAlPiUKICAgcmVuYW1lKG1lZGljYWlkX2Vucm9sbG1lbnQgPSB2YWx1ZSkgJT4lCiAgIGRwbHlyOjpzZWxlY3QoU3RhdGVfTmFtZSwgeWVhciwgbWVkaWNhaWRfZW5yb2xsbWVudCkKCnN0YXRlX21lZGljYWlkZW5yb2xsX2xvbmcKYGBgCgoKYGBge3IgcmVhZCBhbmQgbWVyZ2UgTlNEVUggZHJ1ZyB1c2UgZGF0YSAoZGVtYW5kIG1lYXN1cmVzKSBmcm9tIHRoZSBhZ2dyZWdhdGVkIGNzdiBmaWxlIGZyb20gZGFzaGJvYXJkfQoKIyBjbGVhbl9uc2R1aF9maWxlcyA8LSBmdW5jdGlvbihmb2xkZXJfcGF0aCwgbWVhc3VyZV9uYW1lKQojIHsKIyAgICNjcmVhdGUgY29sdW1ucyB0byBzYXZlIHRoZSBjb25maWRlbmNlIGludGVydmFscyBpbiAKIyAgIG1lYXN1cmVfdXBwZXIgPC0gcGFzdGUobWVhc3VyZV9uYW1lLCAiX2NpdXBwZXIiLCBzZXAgPSAiIikKIyAgIG1lYXN1cmVfbG93ZXIgPC0gcGFzdGUobWVhc3VyZV9uYW1lLCAiX2NpbG93ZXIiLCBzZXAgPSAiIikKIyAgIAojICAgI2xvb3AgdGhyb3VnaCBhbGwgZGF0YSBpbiB0aGUgZm9sZGVyLCByZWZvcm1hdCwgYW5kIHNhdmUgaXQKIyAgIHllYXJfZGF0YSA8LSBsaXN0KCkKIyAgIG5zZHVoX2ZpbGVzIDwtIGxpc3QuZmlsZXMocGF0aCA9IGZvbGRlcl9wYXRoKQojICAgcHJpbnQobnNkdWhfZmlsZXMpCiMgICBpbmRleCA8LSAxCiMgICAKIyAgICNsb29wIHRocm91Z2ggYWxsIHRoZSBmaWxlcyBpbiB0aGUgZm9sZGVyIAojICAgZm9yIChmaWxlIGluIG5zZHVoX2ZpbGVzKQojICAgewojICAgICAgIHRoaXNfZGF0YSA8LSByZWFkLmNzdihwYXN0ZShmb2xkZXJfcGF0aCwgZmlsZSwgc2VwID0gIiIpKSAlPiUKIyAgICAgICAgICAgI3JvdW5kIHRoZSB5ZWFyIHJhbmdlIChpLmUuIDIwMTMtMjAxNCkgdXAsIHNvIHdlIGFyZSBzYXZpbmcgaXQgYXMgdGhlIHllYXJfZW5kCiMgICAgICAgICAgIHNlcGFyYXRlKHllYXJfcGFpciwgaW50byA9IGMoTkEsICJ5ZWFyX2VuZCIpKSAlPiUKIyAgICAgICAgICAgbXV0YXRlKHllYXJfZW5kID0gcGFzdGUoIjIwIiwgeWVhcl9lbmQsIHNlcCA9ICIiKSkgJT4lCiMgICAgICAgICAgIHJlbmFtZSghIW1lYXN1cmVfbmFtZSA6PSBlc3RpbWF0ZSwKIyAgICAgICAgICAgICAgICAgICEhbWVhc3VyZV9sb3dlciA6PSBjaV9sb3dlciwKIyAgICAgICAgICAgICAgICAgICEhbWVhc3VyZV91cHBlciA6PSBjaV91cHBlcikgJT4lIAojICAgICAgICAgICBkcGx5cjo6c2VsZWN0KC1jKG91dGNvbWUsIGFnZV9ncm91cCkpCiMgICAgICAgCiMgICAgICAgI2FkZCBpdCB0byBhIGxpc3QKIyAgICAgICB5ZWFyX2RhdGFbW2luZGV4XV0gPC0gdGhpc19kYXRhCiMgICAgICAgaW5kZXggPC0gaW5kZXggKyAxCiMgICB9CiMgCiMgICAjYXBwZW5kIHRoZSBkYXRhIGZyb20gZWFjaCBmaWxlIGludG8gb25lIGRhdGFmcmFtZSBhbmQgcmV0dXJuCiMgICByZXR1cm4oYmluZF9yb3dzKHllYXJfZGF0YSkpCiMgfQojIAojIAojIHN1ZF9wYXN0eWVhciA8LSBjbGVhbl9uc2R1aF9maWxlcygiRGF0YS9OU0RVSC9OU0RVSF9TVUQvIiwgInN1ZF9wYXN0eWVhciIpCiMgbmVlZGluZ19ub3RyZWNlaXZpbmcgPC0gY2xlYW5fbnNkdWhfZmlsZXMoIkRhdGEvTlNEVUgvTlNEVUhfTmVlZGluZ05vdFJlY2VpdmluZy8iLCAibmVlZGluZ190eCIpCiMgYmluZ2VhbGNvaG9sX3Bhc3Rtb250aCA8LSBjbGVhbl9uc2R1aF9maWxlcygiRGF0YS9OU0RVSC9OU0RVSF9CaW5nZUFsY29ob2wvIiwgImJpbmdlYWxjb2hvbF9wYXN0bW9udGgiKQojIGRydWdfcGFzdG1vbnRoIDwtIGNsZWFuX25zZHVoX2ZpbGVzKCJEYXRhL05TRFVIL05TRFVIX0lsbGljaXREcnVnVXNlLyIsICJkcnVnX3Bhc3Rtb250aCIpCiMgCiMgc3VkX2RlbWFuZF9kZiA8LSBzdWRfcGFzdHllYXIgJT4lIAojICAgbGVmdF9qb2luKG5lZWRpbmdfbm90cmVjZWl2aW5nLCBieT0gYygic3RhdGUiLCAieWVhcl9lbmQiKSkgJT4lCiMgICBsZWZ0X2pvaW4oYmluZ2VhbGNvaG9sX3Bhc3Rtb250aCwgYnk9IGMoInN0YXRlIiwgInllYXJfZW5kIikpICU+JQojICAgbGVmdF9qb2luKGRydWdfcGFzdG1vbnRoLCBieSA9IGMoInN0YXRlIiwgInllYXJfZW5kIikpCiMgCiMgc3VkX2RlbWFuZF9kZgoKYGBgCgoKClJlYWQgYWxsIE5TRFVIIGRhdGEgZnJvbSBoZXJlOiBodHRwczovL3d3dy5zYW1oc2EuZ292L2RhdGEvbnNkdWgvc3RhdGUtcmVwb3J0cwpgYGB7ciByZWFkIGluIHRoZSBjb21iaW5lZCBuc2R1aCBmaWxlfQpsaWJyYXJ5KGhhdmVuKQpuc2R1aF85OV8xOSA8LSBoYXZlbjo6cmVhZF9zYXMoIi4uL0RhdGEvTlNEVUgvTlNEVUhfOTlfMTlfc3RhdGVfc2Flc19maW5hbC5zYXM3YmRhdCIpCgoKbnNkdWhfMjFfMjMgPC0gaGF2ZW46OnJlYWRfc2FzKCIuLi9EYXRhL05TRFVIL3N0YXRlX3NhZXNfZmluYWxfMjEyMl8yMl8yMjIzLnNhczdiZGF0IikKCiNoaXR0aW5nIGEgaGljY3VwIHdpdGggMjAyMS0yMDIzIE5TRFVIIGRhdGEgLSBkb2N1bWVudGF0aW9uIHNheXMgdGhhdCB0aGUgcHJldmlvdXMgeWVhcnMgY2Fubm90IGJlIGNvbXBhcmVkIHRvIDIwMjEtMjAyMwojIGh0dHBzOi8vd3d3LnNhbWhzYS5nb3YvZGF0YS9zaXRlcy9kZWZhdWx0L2ZpbGVzL3JlcG9ydHMvcnB0NTYxOTgvMjAyMy1uc2R1aC1wdWYtZGF0YS11c2Vycy1ndWlkZS5wZGYKI25zZHVoXzIwMjAgPC0gcmVhZC50YWJsZSgiLi4vRGF0YS9OU0RVSC9OU0RVSF8yMDIwX1RhYi50eHQiLCBoZWFkZXIgPSBUUlVFLCBzZXAgPSAnXHQnKQojbnNkdWhfMjAyMSA8LSByZWFkLnRhYmxlKCIuLi9EYXRhL05TRFVIL05TRFVIXzIwMjFfVGFiLnR4dCIsIGhlYWRlciA9IFRSVUUsIHNlcCA9ICdcdCcpCiNuc2R1aF8yMDIyIDwtIHJlYWQudGFibGUoIi4uL0RhdGEvTlNEVUgvTlNEVUhfMjAyMl9UYWIudHh0IiwgaGVhZGVyID0gVFJVRSwgc2VwID0gJ1x0JykKI25zZHVoXzIwMjMgPC0gcmVhZC50YWJsZSgiLi4vRGF0YS9OU0RVSC9OU0RVSF8yMDIzX1RhYi50eHQiLCBoZWFkZXIgPSBUUlVFLCBzZXAgPSAnXHQnKQoKYGBgCgoKCgoKbG9va2luZyBmb3IgdmFyaWFibGVzIHdoaWNoIGNhbiBtZWFzdXJlIGRlbWFuZCBidXQgYXJlIGNvbnNpc3RlbnRseSBhdmFpbGFibGUgZm9yIGEgbG9uZ2VyIHBlcmlvZCBvZiB0aW1lIC0gCmFsY29ob2wgdXNlIGRpc29yZGVyIGluIHRoZSBwYXN0IHllYXIsIChBQk9EQUxDKQpjb2NhaW5lIHVzZSBpbiB0aGUgcGFzdCB5ZWFyLCAoQ09DWVIpCmhlcm9pbiB1c2UgaW4gdGhlIHBhc3QgeWVhciwgKEhFUllSKQptYXJpanVhbmEgdXNlIGluIHRoZSBwYXN0IG1vbnRoICAoTVJKTU9OKSAtIG1vbnRoIGNob3NlbiBvdmVyIHllYXIgYmVjYXVzZSBpdCBpcyBtb3JlIGZyZXF1ZW50IGFuZCBtb3JlIGxpa2VseSByZXByZXNlbnRzIGhpZ2ggdXNlIC8gdXNlIGRpc29yZGVyIAoKKHByb2JhYmx5IHdvbid0IGluY2x1ZGUgdG9iYWNjbyB1c2UgYmVjYXVzZSBpdCBpc250IGFzIG9mdGVuIHRyZWF0ZWQgaW4gYSBzcGVjaWFsdHkgZmFjaWxpdHkpCgoKCgoKYGBge3IgY2xlYW4gdGhlIG5zZHVoIGRhdGF9CgpjbGVhbl9uc2R1aF9kYXRhIDwtIGZ1bmN0aW9uKG5zZHVoX2RhdGEpewogI2ZpbHRlciB0aGUgZGF0YSB0byBvbmx5IHN0YXRlIHJlcG9ydHMsIGFuZCB5ZWFycyBwb3N0LTIwMTUgCm5zZHVoX2RhdGFfbG9uZyA8LSBuc2R1aF9kYXRhICU+JSAKICBzZXBhcmF0ZShweWVhcm5tLCBpbnRvID0gYygic3RhcnRfeWVhciIsICJlbmRfeWVhciIpLCAiLSIpICU+JQogIGZpbHRlcihhcmVhID09IDIpICU+JSAKICBmaWx0ZXIob3V0Y29tZSAlaW4lIG5zZHVoX291dGNvbWVzKSAlPiUKICBmaWx0ZXIoYWdlZ3JwICA9PSA0KSAlPiUgI2ZpbHRlciB0byBwZW9wbGUgYWJvdmUgMTggKGFkdWx0cykKICBtdXRhdGUoc3RuYW1lX2xvd2VyID0gdG9sb3dlcihzdG5hbWUpKSAlPiUKICBkcGx5cjo6c2VsZWN0KG91dG5hbWUsIG91dGNvbWUsIHN0YXJ0X3llYXIsIGVuZF95ZWFyLCBhZ2VncnAsIHN0bmFtZSxzdG5hbWVfbG93ZXIsIEJTQUUsIGxvd19zYWUsIHVwX3NhZSkKICAgICAgICAgICAgICAgICNwb3AsIGVzdF90b3RhbCwgbG93X3RvdGFsLCB1cF90b3RhbCkgI2kgd2FzIHByZXZpb3VzbHkgdXNpbmcgZXN0X3RvdGFsIGJ1dCB0aGlzIGlzIHRoZSBhdmVyYWdlIG51bWJlciBvZiBwZW9wbGUgcGVyIHN0YXRlIHdoaWNoIHdpbGwgYmUgZGVwZW5kZW50IG9uIHBvcHVsYXRpb24KCm5zZHVoX2RhdGFfd2lkZSA8LSBuc2R1aF9kYXRhX2xvbmcgJT4lCiAgc2VsZWN0KHN0bmFtZSwgc3RhcnRfeWVhciwgZW5kX3llYXIsIG91dGNvbWUsIEJTQUUpICU+JQogIHBpdm90X3dpZGVyKGlkX2NvbHMgPSBjKHN0bmFtZSwgZW5kX3llYXIpLCBuYW1lc19mcm9tID0gb3V0Y29tZSwgdmFsdWVzX2Zyb20gPSBCU0FFLCB1bnVzZWRfZm4gPSBmaXJzdCkKCiAgcmV0dXJuKG5zZHVoX2RhdGFfd2lkZSkgCn0KI2ludGVyZXN0ZWQgaW4gNCBzdWJzdGFuY2UgdXNlIG91dGNvbWVzCm5zZHVoX291dGNvbWVzIDwtIGMoIkJOR0RSSyIsICJJTExFTU1PTiIsICJUWE5QSUxBTCIsICJVRFBZSUxBTCIsICJIRVJZUiIsICJBQk9EQUxDIiwgIlVEWVI1QUxDIiwgIkNPQ1lSIiwgIkhFUllSIiwgIk1SSk1PTiIpCgpuc2R1aF9kYXRhX3dpZGUgPC0gY2xlYW5fbnNkdWhfZGF0YShuc2R1aF85OV8xOSkKbnNkdWhfZGF0YV93aWRlXzIxIDwtIGNsZWFuX25zZHVoX2RhdGEobnNkdWhfMjFfMjMpCgoKbnNkdWhfZGF0YV93aWRlCm5zZHVoX2RhdGFfd2lkZV8yMQoKYGBgCgoKYGBge3IgbWVyZ2UgZGlmZmVyZW50IHN0YXRlbGV2ZWwgY29udHJvbCB2YXJpYWJsZXMgdG9nZXRoZXJ9CgojdGhpcyBmdW5jdGlvbiBhc3N1bWVzIHRoYXQgc3RhdGVwb3BfbG9uZywgc3RhdGVfaGVhbHRoc3BlbmRpbmdfbG9uZywgYW5kIHN0YXRlX21lZGljYWlkZW5yb2xsX2xvbmcgYXJlIHJlYWQgaW50byBtZW1vcnkgYWxyZWFkeQptZXJnZV9jb250cm9sX3ZhcnMgPC0gZnVuY3Rpb24obnNkdWhfZGF0YSwgYWxjX2NvbG5hbWUpCnsKICAKICBuc2R1aF9kYXRhJHN0bmFtZSA8LSB0cmltd3MobnNkdWhfZGF0YSRzdG5hbWUpCiAgCiAgc3RhdGVfY29udHJvbF9sb25nIDwtIHN0YXRlX2hlYWx0aHNwZW5kaW5nX2xvbmcgJT4lCiAgICAjc3RhdGVwb3BfbG9uZyAlPiUgCiAgI2lubmVyX2pvaW4oc3RhdGVfaGVhbHRoc3BlbmRpbmdfbG9uZywgYnkgPSBjKCJTdGF0ZV9OYW1lIj0gIlN0YXRlX05hbWUiLCAieWVhciIgPSAieWVhciIpKSAlPiUKICBpbm5lcl9qb2luKHN0YXRlX21lZGljYWlkZW5yb2xsX2xvbmcsIGJ5ID0gYygiU3RhdGVfTmFtZSI9ICJTdGF0ZV9OYW1lIiwgInllYXIiID0gInllYXIiKSkgJT4lCiAgI211dGF0ZShtZWRpY2FpZF9lbnJvbGxfcGVyY2FwaXRhID0gbWVkaWNhaWRfZW5yb2xsbWVudCAvIHBvcF90aG91c2FuZHMpICU+JQogIAogICAgCiAgICAjam9pbiAiZGVtYW5kIiBtZWFzdXJlcyBmcm9tIE5TRFVIIGRhdGEKICAjbGVmdF9qb2luKG5zZHVoX2RhdGEsIGJ5ID0gYygiU3RhdGVfTmFtZSIgPSAic3RuYW1lIiwgInllYXIiID0gImVuZF95ZWFyIikpICU+JSAKICAjY2hhbmdpbmcgdG8gcmlnaHQgam9pbiBvbiA2LzEyIGJlY2F1c2Ugd2UgZG9uJ3QgaGF2ZSBjb250cm9sIGRhdGEgZm9yIDIwMjEtMjAyMyB5ZXQKICByaWdodF9qb2luKG5zZHVoX2RhdGEsIGJ5ID0gYygiU3RhdGVfTmFtZSIgPSAic3RuYW1lIiwgInllYXIiID0gImVuZF95ZWFyIikpICU+JSAKICAjam9pbiBzdGF0ZSBhYmJyZXZpYXRpb25zIG9udG8gZGF0YWZyYW1lCiAgbXV0YXRlKHN0YXRlX25hbWVfbG93ZXIgPSB0b2xvd2VyKFN0YXRlX05hbWUpKSAlPiUKICBsZWZ0X2pvaW4oc3RhdGVfYWJicmV2c19kZiwgYnkgPSBjKCJzdGF0ZV9uYW1lX2xvd2VyIiA9ICJzdGF0ZV9uYW1lcyIpKSAlPiUKICBkcGx5cjo6c2VsZWN0KC1jKHNwZW5kaW5nX3R5cGUsIHN0YXRlX25hbWVfbG93ZXIpKSAlPiUKICByZW5hbWUoImJpbmdlX2RyaW5raW5nIiA9IEJOR0RSSywgImlsbGljaXRfZHJ1Z3VzZSIgPSBJTExFTU1PTiwgCiAgICAgICAgICMibmVlZGluZ190eCI9IFRYTlBJTEFMLCAKICAgICAgICAgIyJzdWQiID0gVURQWUlMQUwsCiAgICAgICAgICJhdWRfeXIiID0ge3thbGNfY29sbmFtZX19LCAKICAgICAgICAgImhlcm9pbl95ciI9SEVSWVIsICJjb2NhaW5lX3lyIj1DT0NZUiwgIm1hcmlqdWFuYV9tb250aCIgPSBNUkpNT04pCgogIHJldHVybihzdGF0ZV9jb250cm9sX2xvbmcpCn0KCnN0YXRlX2NvbnRyb2xfbG9uZzE0IDwtIG1lcmdlX2NvbnRyb2xfdmFycyhuc2R1aF9kYXRhX3dpZGUsICJBQk9EQUxDIikKc3RhdGVfY29udHJvbF9sb25nMjEgPC0gbWVyZ2VfY29udHJvbF92YXJzKG5zZHVoX2RhdGFfd2lkZV8yMSwgIlVEWVI1QUxDIikKCnN0YXRlX2NvbnRyb2xfbG9uZyA8LSBiaW5kX3Jvd3Moc3RhdGVfY29udHJvbF9sb25nMTQsIHN0YXRlX2NvbnRyb2xfbG9uZzIxKQpzdGF0ZV9jb250cm9sX2xvbmcgPC0gc3RhdGVfY29udHJvbF9sb25nICU+JSBmaWx0ZXIoc3RhcnRfeWVhciA+IDIwMTIpCnN0YXRlX2NvbnRyb2xfbG9uZwpgYGAKCgoKU2NhbGUgdGhlIHZhcmlhYmxlcyBhbmQgbGFnIHRoZSBuZWVkIHZhcmlhYmxlcyAKCmBgYHtyfQojc2NhbGUgdG8gaGVhbHRoIHNwZW5kaW5nIGluIHRob3VzYW5kcyBvZiBkb2xsYXJzCnN0YXRlX2NvbnRyb2xfbG9uZyRwZXJjYXBpdGFfaGVhbHRoX3NwZW5kaW5nX3Rob3VzYW5kcyA8LSBzdGF0ZV9jb250cm9sX2xvbmckcGVyY2FwaXRhX2hlYWx0aF9zcGVuZGluZyAvIDEwMDAKI3NjYWxlIHRvIHBvcHVsYXRpb24gaW4gbWlsbGlvbnMgCiNzdGF0ZV9jb250cm9sX2xvbmckcG9wX21pbGxpb25zIDwtIHN0YXRlX2NvbnRyb2xfbG9uZyRwb3BfdGhvdXNhbmRzIC8gMTAwMAoKI2NoYW5nZSB0aGUgZGVtYW5kIHZhcmlhYmxlcyB0byBwZXJjZW50cwpzdGF0ZV9jb250cm9sX2xvbmckYmluZ2VfZHJpbmtpbmcgPC0gc3RhdGVfY29udHJvbF9sb25nJGJpbmdlX2RyaW5raW5nICogMTAwCnN0YXRlX2NvbnRyb2xfbG9uZyRpbGxpY2l0X2RydWd1c2UgPC0gc3RhdGVfY29udHJvbF9sb25nJGlsbGljaXRfZHJ1Z3VzZSAqIDEwMAojc3RhdGVfY29udHJvbF9sb25nJHN1ZCA8LSBzdGF0ZV9jb250cm9sX2xvbmckc3VkICogMTAwIAojc3RhdGVfY29udHJvbF9sb25nJG5lZWRpbmdfdHggPC0gc3RhdGVfY29udHJvbF9sb25nJG5lZWRpbmdfdHggKiAxMDAKc3RhdGVfY29udHJvbF9sb25nJGF1ZF95ciA8LSBzdGF0ZV9jb250cm9sX2xvbmckYXVkX3lyICogMTAwCnN0YXRlX2NvbnRyb2xfbG9uZyRoZXJvaW5feXIgPC0gc3RhdGVfY29udHJvbF9sb25nJGhlcm9pbl95ciAqIDEwMApzdGF0ZV9jb250cm9sX2xvbmckY29jYWluZV95ciA8LSBzdGF0ZV9jb250cm9sX2xvbmckY29jYWluZV95ciAqIDEwMApzdGF0ZV9jb250cm9sX2xvbmckbWFyaWp1YW5hX21vbnRoIDwtIHN0YXRlX2NvbnRyb2xfbG9uZyRtYXJpanVhbmFfbW9udGggKiAxMDAKCiNsYWcgdGhlIDQgZGVtYW5kIHZhcmlhYmxlcyAsIGFuZCBjaGFuZ2UgdGhlbSB0byBwZXJjZW50YWdlcyAKc3RhdGVfY29udHJvbF9sb25nIDwtIHN0YXRlX2NvbnRyb2xfbG9uZyAlPiUKICAgICAgICAgICAgICAgICAgICBhcnJhbmdlKFN0YXRlX05hbWUsIHllYXIpICU+JSAgIyBFbnN1cmUgZGF0YSBpcyBvcmRlcmVkIGJ5IFN0YXRlX0FiYnJldiBhbmQgeWVhcgogICAgICAgICAgICAgICAgICAgIGdyb3VwX2J5KFN0YXRlX05hbWUpICU+JQogICAgICAgICAgICAgICAgICAgIG11dGF0ZShwcmV2MnllYXJzX2JpbmdlZHJpbmtpbmcgPSBkcGx5cjo6bGFnKGJpbmdlX2RyaW5raW5nKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJldjJ5ZWFyc19kcnVndXNlID0gZHBseXI6OmxhZyhpbGxpY2l0X2RydWd1c2UpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAjcHJldjJ5ZWFyc19zdWQgPSBkcGx5cjo6bGFnKHN1ZCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICNwcmV2MnllYXJzX25lZWRpbmd0eCA9IGRwbHlyOjpsYWcobmVlZGluZ190eCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZXYyeWVhcnNfYXVkID0gZHBseXI6OmxhZyhhdWRfeXIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICBwcmV2MnllYXJzX21hcmlqdWFuYSA9IGRwbHlyOjpsYWcobWFyaWp1YW5hX21vbnRoKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgZHJ1Z3VzZV9jYWxjID0gKGNvY2FpbmVfeXIgKyBoZXJvaW5feXIpLzIsICNjb21iaW5lIHRoZSAyIGRydWcgdXNlIG1ldHJpY3MgLSBhdmVyYWdlIAogICAgICAgICAgICAgICAgICAgICAgICAgICAjQldPIDUvMjItIGNoYW5naW5nIHRoZSBhYm92ZSBtZXRyaWMgdG8gZGl2aWRlIGJ5IDIgZm9yIHRoZSBwcmV2YWxlbmNlIG9mIGRydWcgdXNlIHBlciAxMDAKICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJldjJ5ZWFyc19kcnVndXNlY2FsYyA9IGRwbHlyOjpsYWcoZHJ1Z3VzZV9jYWxjKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJldjJ5ZWFyc19jb2NhaW5lID0gZHBseXI6OmxhZyhjb2NhaW5lX3lyKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJldjJ5ZWFyc19oZXJvaW4gPSBkcGx5cjo6bGFnKGhlcm9pbl95cikpCmBgYAoKCgpgYGB7ciBwaXZvdCBzdGF0ZSB0cmVhdG1lbnQgY2VudGVyIGNvdW50cyB0byBsb25nIGFuZCBtZXJnZSB0byBjb250cm9sIHZhcmlhYmxlc30KCiNwaXZvdCBkYXRhIHRvIGxvbmcgZm9ybWF0CiNzdGF0ZV9maW5hbF9kZiA8LSBwcm9maXRfc3RhdGVzXzE0MTkgJT4lCnN0YXRlX2ZpbmFsX2RmIDwtIHByb2ZpdF9zdGF0ZXNfMTQyMyAlPiUKICBkcGx5cjo6c2VsZWN0KFNUQVRFLCBjb250YWlucygiY291bnQiKSkgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjb250YWlucygiY291bnQiKSkgJT4lCiAgc2VwYXJhdGUobmFtZSwgaW50byA9IGMoTkEsICJwcm9maXRfdHlwZSIsICJ5ZWFyIiksICJfIikgJT4lCiAgcmVuYW1lKFN0YXRlX0FiYnJldiA9IFNUQVRFLCBjb3VudF90eCA9IHZhbHVlKSAlPiUKICBtdXRhdGUoU3RhdGVfQWJicmV2ID0gYXMuY2hhcmFjdGVyKFN0YXRlX0FiYnJldiksIHllYXIgPSBhcy5jaGFyYWN0ZXIoeWVhcikpICU+JQojam9pbiB0byBjb250cm9sIHZhcmlhYmxlcwogIGxlZnRfam9pbihzdGF0ZV9jb250cm9sX2xvbmcsIGJ5ID0gYygiU3RhdGVfQWJicmV2IiA9ICJzdGF0ZV9hYmJyZXZzIiwgInllYXIiID0gInllYXIiKSkgIyU+JQogICNmaWx0ZXIoeWVhciA+PSAyMDE2ICYgeWVhciA8PSAyMDIwKSAlPiUKICAjbXV0YXRlKHR4X3BlcmNhcGl0YSA9IGNvdW50X3R4IC8gKHBvcF90aG91c2FuZHMqMTAwMCkpCgpoZWFkKHN0YXRlX2ZpbmFsX2RmKQpgYGAKCgpNZXJnaW5nIGZvbGxvd2luZyB2YXJpYWJsZXM6CiogcmFjZQoqIGdlbmRlcgoqIGV0aG5pY2l0eQoKCgpgYGB7ciByZWFkIGluIHRoZSByYWNlL2dlbmRlci9ldGhuaWNpdHkgZGF0YX0KCiNyZWFkIGRlbW9ncmFwaGljIGluZm9ybWF0aW9uIGZyb20gMSB5ZWFyIGZyb20gdGhlIFdPTkRFUiBDREMgZGF0YXNldApyZWFkX2NsZWFuX2RlbW9ncmFwaGljIDwtIGZ1bmN0aW9uKGZpbGVwYXRoLCB5ZWFyX3BhcmFtKQp7CiAgZGVtb2dyYXBoaWNfc3RhdGVzIDwtIHJlYWQudGFibGUoZmlsZXBhdGgsIHNlcCA9ICJcdCIsIAogICAgICAgICAgIGZpbGwgPSBUUlVFLAogICAgICAgICAgIGhlYWRlciA9IFRSVUUpICU+JQogICAgI2FmdGVyIDIwMjAgaXQgaXMgYSAiU2V4IiB2YXJpYWJsZSBpbnN0ZWFkIG9mICJHZW5kZXIiCiAgICByZW5hbWUoYW55X29mKGMoR2VuZGVyID0gIlNleCIpKSkgJT4lCiAgZmlsdGVyKCFpcy5uYShQb3B1bGF0aW9uKSwjZmlsdGVyIG91dCB1bm5lY2Vzc2FyeSB0ZXh0IGF0IHRoZSBib3R0b20gCiAgICAgICAgIEdlbmRlciAhPSAiIiwgI2ZpbHRlciB0byB0aGUgbW9zdCBncmFudWxhciBsZXZlbCBvZiBlYWNoIGNvbWJpbmF0aW9uIG9mIGdlbmRlci9SYWNlL0V0aG5pY2l0eSBhbmQgdGhlbiB3ZSBjYW4gYWdncmVnYXRlIHVwCiAgICAgICAgIFJhY2UgIT0gIiIsIAogICAgICAgICBFdGhuaWNpdHkgIT0gIiIpIAoKZ2VuZGVyX2RmIDwtIGRlbW9ncmFwaGljX3N0YXRlcyAlPiUgIAogIGFycmFuZ2UoU3RhdGVzKSAlPiUgCiAgZ3JvdXBfYnkoU3RhdGVzLCBHZW5kZXIpICU+JSAKICBzdW1tYXJpemUoY291bnQgPSBzdW0oUG9wdWxhdGlvbikpICU+JQogICNjaGFuZ2UgdGhlIGNvdW50IHBlciBnZW5kZXIgaW50byBhIHBlcmNlbnQKICBtdXRhdGUoVG90YWwgPSBzdW0oYWNyb3NzKHdoZXJlKGlzLm51bWVyaWMpKSksCiAgICAgICAgIFBlcmNlbnQgPSAoY291bnQgLyBUb3RhbCkgKiAxMDApICAlPiUgCiAgIHVuZ3JvdXAoKSAlPiUKICBwaXZvdF93aWRlcihpZF9jb2xzID0gU3RhdGVzLCBuYW1lc19mcm9tID0gR2VuZGVyLCB2YWx1ZXNfZnJvbSA9IFBlcmNlbnQsIG5hbWVzX2dsdWUgPSAiR2VuZGVyX3tHZW5kZXJ9IikgCgpyYWNlX2RmIDwtIGRlbW9ncmFwaGljX3N0YXRlcyAlPiUgIAogIGFycmFuZ2UoU3RhdGVzKSAlPiUgCiAgZ3JvdXBfYnkoU3RhdGVzLCBSYWNlKSAlPiUgCiAgc3VtbWFyaXplKGNvdW50ID0gc3VtKFBvcHVsYXRpb24pKSAlPiUKICAjY2hhbmdlIHRoZSBjb3VudCBwZXIgUmFjZSBpbnRvIGEgcGVyY2VudAogIG11dGF0ZShUb3RhbCA9IHN1bShhY3Jvc3Mod2hlcmUoaXMubnVtZXJpYykpKSwKICAgICAgICAjY2hhbmdlIHRoZSBwZXJjZW50IGZyb20gYSBkZWNpbWFsIChpLmUuIDEwJSA9IDAuMSkgdG8gYSBwZXJjZW50IChpLmUgMTAlID0gMTApIHRvIGNvcnJlc3BvbmQgd2l0aCBvdGhlciB2YXJpYWJsZXMnIGZvcm1hdCBpbiBkZgogICAgICAgICBQZXJjZW50ID0gKGNvdW50IC8gVG90YWwpICogMTAwKSAlPiUgCiAgIHVuZ3JvdXAoKSAlPiUKICAjcmVwbGFjZSBhbGwgc3BhY2VzIGluIHRoZSBSYWNlIGNvbHVtbgogIG11dGF0ZShSYWNlID0gZ3N1YigiICIsICIiLCBSYWNlKSkgJT4lIAogICNQaXZvdCB0aGUgcmFjZSBpbnRvIGNvbHVtbnMKICBwaXZvdF93aWRlcihpZF9jb2xzID0gU3RhdGVzLCBuYW1lc19mcm9tID0gUmFjZSwgdmFsdWVzX2Zyb20gPSBQZXJjZW50LCBuYW1lc19nbHVlID0gIlJhY2Vfe1JhY2V9IikgCgpldGhuaWNpdHlfZGYgPC0gZGVtb2dyYXBoaWNfc3RhdGVzICU+JSAgCiAgYXJyYW5nZShTdGF0ZXMpICU+JSAKICBncm91cF9ieShTdGF0ZXMsIEV0aG5pY2l0eSkgJT4lIAogIHN1bW1hcml6ZShjb3VudCA9IHN1bShQb3B1bGF0aW9uKSkgJT4lCiAgI2NoYW5nZSB0aGUgY291bnQgcGVyIEV0aG5pY2l0eSBpbnRvIGEgcGVyY2VudAogIG11dGF0ZShUb3RhbCA9IHN1bShhY3Jvc3Mod2hlcmUoaXMubnVtZXJpYykpKSwKICAgICAgICAgUGVyY2VudCA9IChjb3VudCAvIFRvdGFsKSAqIDEwMCkgICU+JSAKICAgdW5ncm91cCgpICU+JQogICNyZXBsYWNlIGFsbCBzcGFjZXMgaW4gdGhlIEV0aG5pY2l0eSBjb2x1bW4KICBtdXRhdGUoRXRobmljaXR5ID0gZ3N1YigiICIsICIiLCBFdGhuaWNpdHkpKSAlPiUKICAjcGl2b3QgdGhlIGV0aG5pY2l0eSBpbnRvIGNvbHVtbnMKICBwaXZvdF93aWRlcihpZF9jb2xzID0gU3RhdGVzLCBuYW1lc19mcm9tID0gRXRobmljaXR5LCB2YWx1ZXNfZnJvbSA9IFBlcmNlbnQsIG5hbWVzX2dsdWUgPSAiRXRobmljaXR5X3tFdGhuaWNpdHl9IikgCgpkZW1vZ3JhcGhpY3NfZGYgPC0gZ2VuZGVyX2RmICU+JSAKICBtZXJnZShldGhuaWNpdHlfZGYsIGJ5ID0gIlN0YXRlcyIpICU+JQogIG1lcmdlKHJhY2VfZGYsIGJ5ID0gIlN0YXRlcyIpICU+JQogIG11dGF0ZSh5ZWFyID0geWVhcl9wYXJhbSkKCnJldHVybihkZW1vZ3JhcGhpY3NfZGYpCn0KCgpkZW1vZ3JhcGhpY3NfMjAxMyA8LSByZWFkX2NsZWFuX2RlbW9ncmFwaGljKCIuLi9EYXRhL1N0YXRlWWVhcl9EZW1vZ3JhcGhpY0luZm8vU2luZ2xlLVJhY2UgUG9wdWxhdGlvbiBFc3RpbWF0ZXMgMjAxMC0yMDIwIGJ5IFN0YXRlIGFuZCBTaW5nbGUtWWVhciBBZ2VfMjAxMy50eHQiLCAyMDEzKQpkZW1vZ3JhcGhpY3NfMjAxNCA8LSByZWFkX2NsZWFuX2RlbW9ncmFwaGljKCIuLi9EYXRhL1N0YXRlWWVhcl9EZW1vZ3JhcGhpY0luZm8vU2luZ2xlLVJhY2UgUG9wdWxhdGlvbiBFc3RpbWF0ZXMgMjAxMC0yMDIwIGJ5IFN0YXRlIGFuZCBTaW5nbGUtWWVhciBBZ2VfMjAxMy50eHQiLCAyMDE0KQpkZW1vZ3JhcGhpY3NfMjAxNSA8LSByZWFkX2NsZWFuX2RlbW9ncmFwaGljKCIuLi9EYXRhL1N0YXRlWWVhcl9EZW1vZ3JhcGhpY0luZm8vU2luZ2xlLVJhY2UgUG9wdWxhdGlvbiBFc3RpbWF0ZXMgMjAxMC0yMDIwIGJ5IFN0YXRlIGFuZCBTaW5nbGUtWWVhciBBZ2VfMjAxMy50eHQiLCAyMDE1KQpkZW1vZ3JhcGhpY3NfMjAxNiA8LSByZWFkX2NsZWFuX2RlbW9ncmFwaGljKCIuLi9EYXRhL1N0YXRlWWVhcl9EZW1vZ3JhcGhpY0luZm8vU2luZ2xlLVJhY2UgUG9wdWxhdGlvbiBFc3RpbWF0ZXMgMjAxMC0yMDIwIGJ5IFN0YXRlIGFuZCBTaW5nbGUtWWVhciBBZ2VfMjAxMy50eHQiLCAyMDE2KQpkZW1vZ3JhcGhpY3NfMjAxNyA8LSByZWFkX2NsZWFuX2RlbW9ncmFwaGljKCIuLi9EYXRhL1N0YXRlWWVhcl9EZW1vZ3JhcGhpY0luZm8vU2luZ2xlLVJhY2UgUG9wdWxhdGlvbiBFc3RpbWF0ZXMgMjAxMC0yMDIwIGJ5IFN0YXRlIGFuZCBTaW5nbGUtWWVhciBBZ2VfMjAxMy50eHQiLCAyMDE3KQpkZW1vZ3JhcGhpY3NfMjAxOCA8LSByZWFkX2NsZWFuX2RlbW9ncmFwaGljKCIuLi9EYXRhL1N0YXRlWWVhcl9EZW1vZ3JhcGhpY0luZm8vU2luZ2xlLVJhY2UgUG9wdWxhdGlvbiBFc3RpbWF0ZXMgMjAxMC0yMDIwIGJ5IFN0YXRlIGFuZCBTaW5nbGUtWWVhciBBZ2VfMjAxMy50eHQiLCAyMDE4KQpkZW1vZ3JhcGhpY3NfMjAxOSA8LSByZWFkX2NsZWFuX2RlbW9ncmFwaGljKCIuLi9EYXRhL1N0YXRlWWVhcl9EZW1vZ3JhcGhpY0luZm8vU2luZ2xlLVJhY2UgUG9wdWxhdGlvbiBFc3RpbWF0ZXMgMjAxMC0yMDIwIGJ5IFN0YXRlIGFuZCBTaW5nbGUtWWVhciBBZ2VfMjAxOS50eHQiLCAyMDE5KQpkZW1vZ3JhcGhpY3NfMjAyMCA8LSByZWFkX2NsZWFuX2RlbW9ncmFwaGljKCIuLi9EYXRhL1N0YXRlWWVhcl9EZW1vZ3JhcGhpY0luZm8vU2luZ2xlLVJhY2UgUG9wdWxhdGlvbiBFc3RpbWF0ZXMgMjAyMC0yMDIyIGJ5IFN0YXRlIGFuZCBTaW5nbGUtWWVhciBBZ2VfMjAyMC54bHMiLCAyMDIwKQpkZW1vZ3JhcGhpY3NfMjAyMSA8LSByZWFkX2NsZWFuX2RlbW9ncmFwaGljKCIuLi9EYXRhL1N0YXRlWWVhcl9EZW1vZ3JhcGhpY0luZm8vU2luZ2xlLVJhY2UgUG9wdWxhdGlvbiBFc3RpbWF0ZXMgMjAyMC0yMDIyIGJ5IFN0YXRlIGFuZCBTaW5nbGUtWWVhciBBZ2VfMjAyMS54bHMiLCAyMDIxKQpkZW1vZ3JhcGhpY3NfMjAyMiA8LSByZWFkX2NsZWFuX2RlbW9ncmFwaGljKCIuLi9EYXRhL1N0YXRlWWVhcl9EZW1vZ3JhcGhpY0luZm8vU2luZ2xlLVJhY2UgUG9wdWxhdGlvbiBFc3RpbWF0ZXMgMjAyMC0yMDIyIGJ5IFN0YXRlIGFuZCBTaW5nbGUtWWVhciBBZ2VfMjAyMi54bHMiLCAyMDIyKQoKCnN0YXRlX2RlbW9ncmFwaGljcyA8LSBiaW5kX3Jvd3MoZGVtb2dyYXBoaWNzXzIwMTMsCiAgICAgICAgICBkZW1vZ3JhcGhpY3NfMjAxNCwKICAgICAgICAgIGRlbW9ncmFwaGljc18yMDE1LAogICAgICAgICAgZGVtb2dyYXBoaWNzXzIwMTYsCiAgICAgICAgICBkZW1vZ3JhcGhpY3NfMjAxNywKICAgICAgICAgIGRlbW9ncmFwaGljc18yMDE4LCAKICAgICAgICAgIGRlbW9ncmFwaGljc18yMDE5LAogICAgICAgICAgZGVtb2dyYXBoaWNzXzIwMjAsCiAgICAgICAgICBkZW1vZ3JhcGhpY3NfMjAyMSwKICAgICAgICAgIGRlbW9ncmFwaGljc18yMDIyKSAlPiUKICBtdXRhdGUoeWVhciA9IGFzLmNoYXJhY3Rlcih5ZWFyKSkgI2Nhc3QgdGhlIHllYXIgY29sdW1uIHRvIGNoYXJhY3RlcgoKI2RlbGV0ZSB1bm5lY2Vzc2FyeSBkZnMgCnJtKGRlbW9ncmFwaGljc18yMDEzLCBkZW1vZ3JhcGhpY3NfMjAxNCwgZGVtb2dyYXBoaWNzXzIwMTUsIGRlbW9ncmFwaGljc18yMDE2LCBkZW1vZ3JhcGhpY3NfMjAxNywgZGVtb2dyYXBoaWNzXzIwMTgsIGRlbW9ncmFwaGljc18yMDE5LCBkZW1vZ3JhcGhpY3NfMjAyMCxkZW1vZ3JhcGhpY3NfMjAyMSwgZGVtb2dyYXBoaWNzXzIwMjIpCmBgYAoKTWVyZ2luZyBpbnN1cmFuY2UgdmFyaWFibGUKKiBpbnN1cmFuY2UKYGBge3IgcmVhZCBpbiBkYXRhIGFib3V0IGluc3VyYW5jZSB0eXBlc30KcmVhZF9jbGVhbl9pbnN1cmFuY2UgPC0gZnVuY3Rpb24ocGF0aCwgeWVhcl9wYXJhbSkKICB7CiAgaW5zdXJhbmNlX3N0YXRlcyA8LSByZWFkLmNzdihwYXRoLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2tpcD0yLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyID0gVFJVRSkgJT4lCiAgZmlsdGVyKCFpcy5uYShUb3RhbCkpICU+JQogIHNlbGVjdCgtRm9vdG5vdGVzKSAlPiUKICBtdXRhdGUoeWVhciA9IHllYXJfcGFyYW0pICU+JQogIHJlbmFtZV93aXRoKH5wYXN0ZTAoIkluc3VyYW5jZV8iLCAueCksIGV2ZXJ5dGhpbmcoKSkgJT4lCiAgICAjcmVtb3ZlIHRoZSAiSW5zdXJhbmNlIiBmcm9tIHllYXIgYW5kIExvY2F0aW9uCiAgcmVuYW1lKHllYXIgPSBJbnN1cmFuY2VfeWVhciwgTG9jYXRpb24gPSBJbnN1cmFuY2VfTG9jYXRpb24pCiAgCiAgI3NvbWUgb2YgdGhlIGNvbHVtbnMgc2hvdyAiPDAuMDEiIC0gY2FsY3VsYXRlIHRoZW0gYnkgc3VidHJhY3RpbmcgZnJvbSB0aGUgb3RoZXIgdmFsdWVzIAogIGluc3VyYW5jZV9zdGF0ZXMgPC0gaW5zdXJhbmNlX3N0YXRlcyAlPiUKICAgIG11dGF0ZShJbnN1cmFuY2VfTWlsaXRhcnkgPSBuYV9pZihhcy5jaGFyYWN0ZXIoSW5zdXJhbmNlX01pbGl0YXJ5KSwgIjwuMDEiKSkgJT4lICNjaGFuZ2UgYW55ICI8LjAxIiB0ZXh0IHRvIG5hCiAgICBtdXRhdGUoSW5zdXJhbmNlX01pbGl0YXJ5ID0gY29hbGVzY2UoYXMubnVtZXJpYyhJbnN1cmFuY2VfTWlsaXRhcnkpLCAxIC0gKEluc3VyYW5jZV9FbXBsb3llciArIEluc3VyYW5jZV9Ob24uR3JvdXAgKyBJbnN1cmFuY2VfTWVkaWNhaWQgKyBJbnN1cmFuY2VfTWVkaWNhcmUgKyBJbnN1cmFuY2VfVW5pbnN1cmVkKSkpICNjYWxjdWxhdGUgdGhlIHJlbWFpbmluZyBwZXJjZW50YWdlCiAgCiAgI2NoYW5nZSB0aGUgZGVjaW1hbHMgdG8gcGVyY2VudHMgCiAgaW5zdXJhbmNlX3N0YXRlcyA8LSBpbnN1cmFuY2Vfc3RhdGVzICU+JSAKICAgICAgICAgICAgICAgICAgICAgIG11dGF0ZSh5ZWFyID0gYXMuY2hhcmFjdGVyKHllYXIpKSAlPiUgIyBlbnN1cmUgdGhlIHllYXIgaXMgYSBjaGFyYWN0ZXIgY29sdW1uCiAgICAgICAgICAgICAgICAgICAgICBtdXRhdGVfaWYoaXMubnVtZXJpYywgfi4gKiAxMDApCiAgCiAgcmV0dXJuKGluc3VyYW5jZV9zdGF0ZXMpCn0KCmluc3VyYW5jZV8yMDEzIDwtIHJlYWRfY2xlYW5faW5zdXJhbmNlKCIuLi9EYXRhL1N0YXRlWWVhcl9JbnN1cmFuY2UvcmF3X2RhdGEyMDEzLmNzdiIsIDIwMTMpCmluc3VyYW5jZV8yMDE0IDwtIHJlYWRfY2xlYW5faW5zdXJhbmNlKCIuLi9EYXRhL1N0YXRlWWVhcl9JbnN1cmFuY2UvcmF3X2RhdGEyMDE0LmNzdiIsIDIwMTQpCmluc3VyYW5jZV8yMDE1IDwtIHJlYWRfY2xlYW5faW5zdXJhbmNlKCIuLi9EYXRhL1N0YXRlWWVhcl9JbnN1cmFuY2UvcmF3X2RhdGEyMDE1LmNzdiIsIDIwMTUpCmluc3VyYW5jZV8yMDE2IDwtIHJlYWRfY2xlYW5faW5zdXJhbmNlKCIuLi9EYXRhL1N0YXRlWWVhcl9JbnN1cmFuY2UvcmF3X2RhdGEyMDE2LmNzdiIsIDIwMTYpCmluc3VyYW5jZV8yMDE3IDwtIHJlYWRfY2xlYW5faW5zdXJhbmNlKCIuLi9EYXRhL1N0YXRlWWVhcl9JbnN1cmFuY2UvcmF3X2RhdGEyMDE3LmNzdiIsIDIwMTcpCmluc3VyYW5jZV8yMDE4IDwtIHJlYWRfY2xlYW5faW5zdXJhbmNlKCIuLi9EYXRhL1N0YXRlWWVhcl9JbnN1cmFuY2UvcmF3X2RhdGEyMDE4LmNzdiIsIDIwMTgpCmluc3VyYW5jZV8yMDE5IDwtIHJlYWRfY2xlYW5faW5zdXJhbmNlKCIuLi9EYXRhL1N0YXRlWWVhcl9JbnN1cmFuY2UvcmF3X2RhdGEyMDE5LmNzdiIsIDIwMTkpCiNpbnN1cmFuY2VfMjAyMCA8LSByZWFkX2NsZWFuX2luc3VyYW5jZSgiLi4vRGF0YS9TdGF0ZVllYXJfSW5zdXJhbmNlL3Jhd19kYXRhMjAyMC5jc3YiLCAyMDIwKQppbnN1cmFuY2VfMjAyMSA8LSByZWFkX2NsZWFuX2luc3VyYW5jZSgiLi4vRGF0YS9TdGF0ZVllYXJfSW5zdXJhbmNlL3Jhd19kYXRhMjAyMS5jc3YiLCAyMDIxKQppbnN1cmFuY2VfMjAyMiA8LSByZWFkX2NsZWFuX2luc3VyYW5jZSgiLi4vRGF0YS9TdGF0ZVllYXJfSW5zdXJhbmNlL3Jhd19kYXRhMjAyMi5jc3YiLCAyMDIyKQoKc3RhdGVfaW5zdXJhbmNlIDwtIGJpbmRfcm93cyhpbnN1cmFuY2VfMjAxMywgaW5zdXJhbmNlXzIwMTQsIGluc3VyYW5jZV8yMDE1LCBpbnN1cmFuY2VfMjAxNiwgaW5zdXJhbmNlXzIwMTcsIGluc3VyYW5jZV8yMDE4LCBpbnN1cmFuY2VfMjAxOSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI2luc3VyYW5jZV8yMDIwLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnN1cmFuY2VfMjAyMSwgaW5zdXJhbmNlXzIwMjIpICU+JQogIG11dGF0ZSh5ZWFyID0gYXMuY2hhcmFjdGVyKHllYXIpKQoKI2RlbGV0ZSB1bm5lY2Vzc2FyeSBkZnMKcm0oaW5zdXJhbmNlXzIwMTMsIGluc3VyYW5jZV8yMDE0LCBpbnN1cmFuY2VfMjAxNSwgaW5zdXJhbmNlXzIwMTYsIGluc3VyYW5jZV8yMDE3LCBpbnN1cmFuY2VfMjAxOCwgaW5zdXJhbmNlXzIwMTksICNpbnN1cmFuY2VfMjAyMCwgCiAgIGluc3VyYW5jZV8yMDIxLCBpbnN1cmFuY2VfMjAyMikKCmBgYAoKCk1lcmdpbmcgcG92ZXJ0eSBhbmQgdW5lbXBsb3ltZW50IHZhcmlhYmxlcwpgYGB7cn0KbGlicmFyeShqYW5pdG9yKSAjdXNlIHRvIG92ZXJ3cml0ZSByb3cgbmFtZXMgCmxpYnJhcnkodGliYmxlKQpsaWJyYXJ5KHJlYWR4bCkKCmZyZWRzX25hbWVfbWFwcGluZyA8LSByZWFkX2V4Y2VsKCIuLi9EYXRhL1N0YXRlWWVhcl9JbmNvbWVfVW5lbXBsb3llZC9TdGF0ZV9Qb3B1bGF0aW9uX1VuZW1wbG95bWVudF9JbmNvbWUueGxzeCIsIHNoZWV0PTIpIAojY3JlYXRlIGEgbmFtZWQgdmVjdG9yIG9mIHRoZSB2YWx1ZXMgZnJvbSB0aGUgbmFtZSBtYXBwaW5nCnN0YXRlX25hbWVzIDwtIGZyZWRzX25hbWVfbWFwcGluZyRTdGF0ZV9QYXJzZWQKbmFtZXMoc3RhdGVfbmFtZXMpIDwtIGZyZWRzX25hbWVfbWFwcGluZyRgU2VyaWVzIElEOmAKCnZhbHVlX25hbWVzIDwtIGZyZWRzX25hbWVfbWFwcGluZyRgVGl0bGU6YApuYW1lcyh2YWx1ZV9uYW1lcykgPC0gZnJlZHNfbmFtZV9tYXBwaW5nJGBTZXJpZXMgSUQ6YAoKZnJlZHNfZGZfdW5mb3JtYXR0ZWQgPC0gcmVhZF9leGNlbCgiLi4vRGF0YS9TdGF0ZVllYXJfSW5jb21lX1VuZW1wbG95ZWQvU3RhdGVfUG9wdWxhdGlvbl9VbmVtcGxveW1lbnRfSW5jb21lLnhsc3giLCBzaGVldD0zKSAKCmZyZWRzX2RmIDwtIGZyZWRzX2RmX3VuZm9ybWF0dGVkICU+JQogICNzd2l0Y2ggdGhlIHJvd3MgYW5kIHRoZSBjb2x1bW5zIHNvIHRoZSB2YWx1ZXMgYXJlIGluIHRoZSByb3dzIGFuZCBjb2x1bW5zIGFyZSB5ZWFycwogIHQoKSAlPiUgIAogICNjYXN0IHRvIGRhdGFmcmFtZQogIGFzLmRhdGEuZnJhbWUoKSAlPiUgCiAgI21vdmUgdGhlIGZpcnN0IHJvdyB0byBiZSB0aGUgaGVhZGVyCiAgamFuaXRvcjo6cm93X3RvX25hbWVzKHJvd19udW1iZXIgPSAxKSAlPiUgCiAgI3JlbmFtZSB0aGUgcm93IG5hbWVzIHRvICJmcmVkc19jb2xuYW1lIgogIHRpYmJsZTo6cm93bmFtZXNfdG9fY29sdW1uKCJmcmVkc19jb2xuYW1lIikgJT4lIAogIG11dGF0ZSh2YWwgPSB2YWx1ZV9uYW1lc1tmcmVkc19jb2xuYW1lXSkgJT4lCiAgI21hcmsgd2hpY2ggdmFyaWFibGVzIHdlIGFyZSBsb29raW5nIGF0IAogIHNlcGFyYXRlKHZhbCwgaW50byA9IGMoInZhcmlhYmxlX21lYXN1cmUiLCAic3RhdGVfbmFtZSIpLCBzZXAgPSAiIGluICIpICU+JSAKICAjcmVtb3ZlICJ0aGUiIGZyb20gREMgbmFtZQogIG11dGF0ZShzdGF0ZV9uYW1lID0gaWZlbHNlKHN0YXRlX25hbWUgPT0gInRoZSBEaXN0cmljdCBvZiBDb2x1bWJpYSIsICJEaXN0cmljdCBvZiBDb2x1bWJpYSIsIHN0YXRlX25hbWUpKSAlPiUgCiAgI3Nob3J0ZW4gdmFyaWFibGUgbWVhc3VyZSBuYW1lcyAKICBtdXRhdGUodmFyaWFibGVfbWVhc3VyZSA9IGlmZWxzZSh2YXJpYWJsZV9tZWFzdXJlID09ICJSZXNpZGVudCBQb3B1bGF0aW9uIiwgIlBvcHVsYXRpb24iLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UodmFyaWFibGVfbWVhc3VyZSA9PSAiVW5lbXBsb3ltZW50IFJhdGUiLCAiVW5lbXBsb3ltZW50IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZSh2YXJpYWJsZV9tZWFzdXJlID09ICJSZWFsIE1lZGlhbiBIb3VzZWhvbGQgSW5jb21lIiwgIkluY29tZSIsICJNSVNTSU5HIikpKSkgJT4lCiAgI3JlbW92ZSBtb250aC9kYXRlIGZyb20geWVhciBuYW1lcyAtIHVubmVjZXNzYXJ5CiAgcmVuYW1lKCIyMDEzIiA9ICIyMDEzLTAxLTAxIiwKICAgICAgICAgIjIwMTQiID0gIjIwMTQtMDEtMDEiLAogICAgICAgICAiMjAxNSIgPSAiMjAxNS0wMS0wMSIsCiAgICAgICAgICIyMDE2IiA9ICIyMDE2LTAxLTAxIiwKICAgICAgICAgIjIwMTciID0gIjIwMTctMDEtMDEiLAogICAgICAgICAiMjAxOCIgPSAiMjAxOC0wMS0wMSIsCiAgICAgICAgICIyMDE5IiA9ICIyMDE5LTAxLTAxIiwKICAgICAgICAgIjIwMjAiID0gIjIwMjAtMDEtMDEiLAogICAgICAgICAiMjAyMSIgPSAiMjAyMS0wMS0wMSIsCiAgICAgICAgICIyMDIyIiA9ICIyMDIyLTAxLTAxIiwKICAgICAgICAgIjIwMjMiID0gIjIwMjMtMDEtMDEiKSAlPiUgCiAgI2NoYW5nZSB0aGUgeWVhcnMgZnJvbSB0aGUgY29sdW1ucyB0byBhIHJvdyBpbmRpY2F0b3IgLSBkYXRhIGlzIG5vdyBpbiBsb25nIGZvcm1hdCB3aXRoIG9uZSByb3cgcGVyIHN0YXRlLXllYXItbWVhc3VyZW1lbnQKICBwaXZvdF9sb25nZXIoY29scyA9IGMoIjIwMTMiLCAiMjAxNCIsICIyMDE1IiwgIjIwMTYiLCAiMjAxNyIsICIyMDE4IiwgIjIwMjAiLCAiMjAxOSIsICIyMDIyIiwgIjIwMjMiKSkgJT4lCiAgcmVuYW1lKCJ5ZWFyIiA9IG5hbWUpICU+JQogICNwaXZvdCB0aGUgaW5kaXZpZHVhbCBtZWFzdXJlcyBpbnRvIGNvbHVtbnMgc28gd2UgaGF2ZSBvbmx5IG9uZSByb3cgcGVyIHN0YXRlLXllYXIKICBwaXZvdF93aWRlcihpZF9jb2xzID0gYyhzdGF0ZV9uYW1lLCB5ZWFyKSwgdmFsdWVzX2Zyb20gPSB2YWx1ZSwgbmFtZXNfZnJvbSA9IHZhcmlhYmxlX21lYXN1cmUpICU+JSAKICAjY2FzdCBudW1lcmljIHZhcmlhYmxlcyB0byBudW1lcmljCiAgbXV0YXRlKHllYXIgPSBhcy5jaGFyYWN0ZXIoeWVhciksIFBvcHVsYXRpb24gPSBhcy5udW1lcmljKFBvcHVsYXRpb24pLCBVbmVtcGxveW1lbnQgPSBhcy5udW1lcmljKFVuZW1wbG95bWVudCksIEluY29tZSA9IGFzLm51bWVyaWMoSW5jb21lKSkKCgpgYGAKCgoKYGBge3IgbWVyZ2UgaW5kZXAuIGFuZCBkZXBlbmQuIHZhcmlhYmxlcyB0byBvdGhlciBjb250cm9sc30Kc3RhdGVfZmluYWxfZGYgPC0gc3RhdGVfZmluYWxfZGYgJT4lCiAgI2pvaW4gZGVtb2dyYXBoaWMgaW5mb3JtYXRpb24KICBsZWZ0X2pvaW4oc3RhdGVfZGVtb2dyYXBoaWNzLCBieSA9IGMoIlN0YXRlX05hbWUiPSJTdGF0ZXMiLCAieWVhciI9InllYXIiKSkgJT4lCiAgI2pvaW4gaW5zdXJhbmNlIGluZm9ybWF0aW9uCiAgbGVmdF9qb2luKHN0YXRlX2luc3VyYW5jZSwgYnkgPSBjKCJTdGF0ZV9OYW1lIj0iTG9jYXRpb24iLCAieWVhciI9InllYXIiKSkgJT4lCiAgI2pvaW4gdGhlIHBvcHVsYXRpb24sIHVuZW1wbG95bWVudCwgYW5kIGluY29tZSBpbmZvcm1hdGlvbgogIGxlZnRfam9pbihmcmVkc19kZiwgYnk9YygiU3RhdGVfTmFtZSI9InN0YXRlX25hbWUiLCAieWVhciI9InllYXIiKSkgJT4lCiAgcmVuYW1lKHBvcF90aG91c2FuZHMgPSBQb3B1bGF0aW9uKSAlPiUKICBtdXRhdGUobWVkaWNhaWRfZW5yb2xsX3BlcmNhcGl0YSA9IG1lZGljYWlkX2Vucm9sbG1lbnQgLyBwb3BfdGhvdXNhbmRzLAogICAgICAgICB0eF9wZXJjYXBpdGEgPSBjb3VudF90eCAvIChwb3BfdGhvdXNhbmRzKjEwMDApLAogICAgICAgICBwb3BfbWlsbGlvbnM9cG9wX3Rob3VzYW5kcy8xMDAwKQogICAgICAgICAKCmhlYWQoc3RhdGVfZmluYWxfZGYpCmBgYAoKCgoKVGhlc2UgYXJlIGF2YWlsYWJsZSBzdGFydGluZyBhdCAyMDEzLTIwMTQ6IAphbGNvaG9sIHVzZSBkaXNvcmRlciBpbiB0aGUgcGFzdCB5ZWFyLCAKY29jYWluZSB1c2UgaW4gdGhlIHBhc3QgeWVhciwgCmhlcm9pbiB1c2UgaW4gdGhlIHBhc3QgeWVhciwgCm1hcmlqdWFuYSB1c2UgaW4gdGhlIHBhc3QgbW9udGggCihwcm9iYWJseSB3b24ndCBpbmNsdWRlIHRvYmFjY28gdXNlIGJlY2F1c2UgaXQgaXNudCBhcyBvZnRlbiB0cmVhdGVkIGluIGEgc3BlY2lhbHR5IGZhY2lsaXR5KQoKYGBge3Igc2VwYXJhdGluZyBkYXRhIGludG8gMyBkaWZmZXJlbnQgZGF0YWZyYW1lc30KIyBzdGF0ZV9mb3Jwcm9maXQgPC0gc3RhdGVfZmluYWxfZGYgJT4lIAojICAgICAgICAgICAgICAgICAgICAgYXJyYW5nZShTdGF0ZV9BYmJyZXYsIHllYXIpICU+JSAgIyBFbnN1cmUgZGF0YSBpcyBvcmRlcmVkIGJ5IFN0YXRlX0FiYnJldiBhbmQgeWVhcgojICAgICAgICAgICAgICAgICAgICAgZ3JvdXBfYnkoU3RhdGVfQWJicmV2KSAlPiUKIyAgICAgICAgICAgICAgICAgICAgIGZpbHRlcihwcm9maXRfdHlwZSA9PSAiRm9ycHJvZml0IiwgIWlzLm5hKHByZXYyeWVhcnNfZHJ1Z3VzZWNhbGMpKSAjMjAxNCBkb2VzIG5vdCBoYXZlIHRoaXMgZGF0YQojIAojIHN0YXRlX25vbnByb2ZpdCA8LSBzdGF0ZV9maW5hbF9kZiAlPiUgCiMgICAgICAgICAgICAgICAgICAgICBhcnJhbmdlKFN0YXRlX0FiYnJldiwgeWVhcikgJT4lICAjIEVuc3VyZSBkYXRhIGlzIG9yZGVyZWQgYnkgU3RhdGVfQWJicmV2IGFuZCB5ZWFyCiMgICAgICAgICAgICAgICAgICAgICBncm91cF9ieShTdGF0ZV9BYmJyZXYpICU+JQojICAgICAgICAgICAgICAgICAgICAgZmlsdGVyKHByb2ZpdF90eXBlID09ICJOb25wcm9maXQiLCAhaXMubmEocHJldjJ5ZWFyc19kcnVndXNlY2FsYykpCiMgCiMgc3RhdGVfZ292dCA8LSBzdGF0ZV9maW5hbF9kZiAlPiUgCiMgICAgICAgICAgICAgICAgICAgICBhcnJhbmdlKFN0YXRlX0FiYnJldiwgeWVhcikgJT4lICAjIEVuc3VyZSBkYXRhIGlzIG9yZGVyZWQgYnkgU3RhdGVfQWJicmV2IGFuZCB5ZWFyCiMgICAgICAgICAgICAgICAgICAgICBncm91cF9ieShTdGF0ZV9BYmJyZXYpICU+JQojICAgICAgICAgICAgICAgICAgICAgZmlsdGVyKHByb2ZpdF90eXBlID09ICJHb3Zlcm5tZW50IiwgIWlzLm5hKHByZXYyeWVhcnNfZHJ1Z3VzZWNhbGMpKQojIAojIAojIHN0YXRlX3RvdGFscyA8LSBzdGF0ZV9maW5hbF9kZiAlPiUKIyAgICAgICAgICAgICAgICAgICBmaWx0ZXIoIWlzLm5hKHByZXYyeWVhcnNfZHJ1Z3VzZWNhbGMpKSAlPiUgICNmaWx0ZXIgb3V0IHJvd3Mgd2UgZG9uJ3Qgd2FudCBmaXJzdCAKIyAgICAgICAgICAgICAgICAgICBncm91cF9ieShTdGF0ZV9BYmJyZXYsIHllYXIpICU+JSAKIyAgICAgICAgICAgICAgICAgICBtdXRhdGUoY291bnRfdHhfdG90YWwgPSBzdW0oY291bnRfdHgsIG5hLnJtID0gVFJVRSkpICU+JSAjY2FsY3VsYXRlIHRoZSB0b3RhbCBudW1iZXIgb2YgdHJlYXRtZW50IGNlbnRlcnMgcGVyIHllYXIgCiMgICAgICAgICAgICAgICAgICAgc2VsZWN0KC1jKGNvdW50X3R4LCBwcm9maXRfdHlwZSkpICU+JSAgI3JlbW92ZSB0aGUgY29sdW1ucyB0aGF0IG9ubHkgYXBwbGllZCB0byBzcGVjaWZpYyB0cmVhdG1lbnQgY2VudGVyIGNvdW50cyAKIyAgICAgICAgICAgICAgICAgICB1bmdyb3VwKCkgJT4lCiMgICAgICAgICAgICAgICAgICAgcmVuYW1lKGNvdW50X3R4ID0gY291bnRfdHhfdG90YWwpICU+JQojICAgICAgICAgICAgICAgICAgIGRpc3RpbmN0KFN0YXRlX0FiYnJldiwgeWVhciwgY291bnRfdHgsIC5rZWVwX2FsbCA9IFRSVUUpIyBnZXQgcmlkIG9mIHRoZSBkdXBsaWNhdGUgcm93cyBvZiBjb250cm9sIHZhcmlhYmxlcyBmb3IgZWFjaCBwcm9maXQgc3RhdHVzCiMgCiMgd3JpdGUuY3N2KHN0YXRlX2ZvcnByb2ZpdCwgIkRhdGEvQ2xlYW5EYXRhL0ZvcnByb2ZpdF9maW5hbGRhdGEuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpCiMgd3JpdGUuY3N2KHN0YXRlX25vbnByb2ZpdCwgIkRhdGEvQ2xlYW5EYXRhL05vbnByb2ZpdF9maW5hbGRhdGEuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpCiMgd3JpdGUuY3N2KHN0YXRlX2dvdnQsICJEYXRhL0NsZWFuRGF0YS9Hb3Zlcm5tZW50X2ZpbmFsZGF0YS5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkKIyB3cml0ZS5jc3Yoc3RhdGVfdG90YWxzLCAiRGF0YS9DbGVhbkRhdGEvVG90YWxzX2ZpbmFsZGF0YS5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkKCmBgYAoKCgpgYGB7ciByZWZvcm1hdHRpbmcgZGF0YSB0byBrZWVwIGZvcnByb2ZpdCwgbm9ucHJvZml0LCBhbmQgZ292ZXJubWVudCBpbiB0aGUgc2FtZSBkYXRhZnJhbWV9CnN0YXRlX2ZpbmFsX2RmIDwtIHN0YXRlX2ZpbmFsX2RmICU+JQogIHBpdm90X3dpZGVyKGlkX2NvbHMgPSBjKFN0YXRlX0FiYnJldiwgeWVhciwgIlN0YXRlX05hbWUiLCAicG9wX21pbGxpb25zIiwgInBlcmNhcGl0YV9oZWFsdGhfc3BlbmRpbmdfdGhvdXNhbmRzIiwgIm1lZGljYWlkX2Vucm9sbF9wZXJjYXBpdGEiLCAicHJldjJ5ZWFyc19kcnVndXNlY2FsYyIsICJwcmV2MnllYXJzX2F1ZCIsICJwcmV2MnllYXJzX21hcmlqdWFuYSIsICJHZW5kZXJfTWFsZSIsICJFdGhuaWNpdHlfSGlzcGFuaWNvckxhdGlubyIsICJSYWNlX1doaXRlIiwgIkluc3VyYW5jZV9Vbmluc3VyZWQiLCAiVW5lbXBsb3ltZW50IiwgIkluY29tZSIpLCAja2VlcCBhbGwgdmFyaWFibGVzIHdlIHdpbGwgbmVlZCBmb3IgdGhlIG1vZGVsCiAgICAgICAgICAgICAgbmFtZXNfZnJvbSA9IHByb2ZpdF90eXBlLCB2YWx1ZXNfZnJvbSA9IGNvdW50X3R4KSAlPiUgCiAgI2NhbGN1bGF0ZSB0aGUgc3VtIG9mIGFsbCBwcm9maXQgdHlwZXMKICByb3d3aXNlKCkgJT4lCiAgICAgICAgICBtdXRhdGUoY291bnRfdHhfdG90YWwgPSBzdW0oRm9ycHJvZml0LCBOb25wcm9maXQsIEdvdmVybm1lbnQsIG5hLnJtID0gVFJVRSkpICU+JQogICNmaWx0ZXIgb25seSB0byBkYXRhIHRoYXQgd2lsbCBhbGxvdyB0aGUgbGFnZ2luZyAKICBmaWx0ZXIoeWVhciA+PSAyMDE1KSAlPiUKICAjcmVwbGFjZSB0aGUgbmFuIGluIEdvdmVybm1lbnQgd2l0aCAwCiAgbXV0YXRlKEdvdmVybm1lbnQgPSBpZmVsc2UoaXMubmEoR292ZXJubWVudCksIDAsIEdvdmVybm1lbnQpKQogIAoKCgpgYGAKCgpgYGB7cn0KZHJ1Z292ZXJkb3NlX2RmIDwtIHJlYWQuY3N2KCIuLi9EYXRhL0NEQ19EcnVnT3ZlcmRvc2VEZWF0aHMuY3N2IikKCiNmb3JtYXQgdGhlIGRhdGEgCmRydWdvdmVyZG9zZV9kZiA8LSBkcnVnb3ZlcmRvc2VfZGYgJT4lCiAgYXJyYW5nZShTVEFURSwgWUVBUikgJT4lCiAgbXV0YXRlKFlFQVIgPSBhcy5jaGFyYWN0ZXIoWUVBUiksCiAgICAgICAgIG92ZXJkb3NlX3JhdGVfbGFnID0gbGFnKFJBVEUpKSAlPiUKICByZW5hbWUob3ZlcmRvc2VfcmF0ZSA9IFJBVEUpICU+JQogIHNlbGVjdChTVEFURSwgWUVBUiwgb3ZlcmRvc2VfcmF0ZSwgb3ZlcmRvc2VfcmF0ZV9sYWcpCgoKI21lcmdlIHRoZSBvdmVyZG9zZSBkYXRhIG9udG8gdGhlIGZpbmFsIGRmCnN0YXRlX2ZpbmFsX2RmIDwtIHN0YXRlX2ZpbmFsX2RmICU+JSAKICBsZWZ0X2pvaW4oZHJ1Z292ZXJkb3NlX2RmLCBieSA9IGMoJ3llYXInPSdZRUFSJywgJ1N0YXRlX0FiYnJldic9J1NUQVRFJykpCmBgYAoKYGBge3Igd3JpdGUgZGF0YSB0byBjc3Z9CndyaXRlLmNzdihzdGF0ZV9maW5hbF9kZiwgIi4uL0RhdGEvQ2xlYW5EYXRhL0FsbHByb2ZpdF9maW5hbGRhdGFfNi4xMi4yNS5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkKYGBgCgoKCkFzIG9mIDYvMTIvMjUgLSBjcmVhdGluZyBhIG5ldyBkYXRhc2V0IHRoYXQgc2VwYXJhdGVzIG91dCB0aGUgT1RQczoKYGBge3J9Cm5zc2F0czIwMTQgJT4lIGZpbHRlcihPVFA9PTEpCgoKT1RQX3Jlc3VsdHMgPC0gbGlzdCgpCk9UUF9pbmRleCA8LSAxCmZvciAoeWVhcl9kZiBpbiB5ZWFyX2RmcykKewogIHRoaXNfZGYgPC0geWVhcl9kZiAlPiUgCiAgICBtdXRhdGUodHlwZSA9IHByb2ZpdF90eXBlc1tPV05FUlNIUF0sCiAgICAgICAgICAgT1RQX2JpbmFyeSA9IGlmZWxzZShPVFAgPT0gMSwgIk9UUCIsICJOb3RfT1RQIikpICU+JQogICAgZmlsdGVyKCEgU1RBVEUgJWluJSBjKCJWSSIsICJHVSIsICJQVyIsICJQUiIsICJGTSIpKSAlPiUgI2ZpbHRlciBvdXQgVVMgdGVycml0b3JpZXMKICAgIGdyb3VwX2J5KFNUQVRFLCBPVFBfYmluYXJ5LCB0eXBlKSAlPiUgCiAgICBzdW1tYXJpemUoY291bnQgPSBuKCkpICU+JQogICAgbXV0YXRlKE9UUF9wcm9maXRfZ3JvdXAgPSBwYXN0ZSh0eXBlLE9UUF9iaW5hcnksIHNlcCA9ICJfIikpICU+JQogICAgdW5ncm91cCgpICU+JQogICAgZ3JvdXBfYnkoU1RBVEUpICU+JQogICAgbXV0YXRlKHBlcmNlbnQgPSBjb3VudCAvIHN1bShjb3VudCkpICU+JSAKICAgIHVuZ3JvdXAoKSAlPiUKICAgIHBpdm90X3dpZGVyKGlkX2NvbHMgPSBTVEFURSwgbmFtZXNfZnJvbSA9IE9UUF9wcm9maXRfZ3JvdXAsIHZhbHVlc19mcm9tID0gYygiY291bnQiLCAicGVyY2VudCIpKSAlPiUgI3Bpdm90IGxvbmcgcm93cyB0byBjb2x1bW5zCiAgICByZW5hbWVfd2l0aCh+IGlmZWxzZSguID09ICJTVEFURSIsIC4sIGFwcGVuZF9udW1iZXIoLiwgeWVhcl9udW1zW09UUF9pbmRleF0pKSwgZXZlcnl0aGluZygpKSAgI2FkZCB0aGUgeWVhciBvbnRvIHRoZSBjb2x1bW5zIHRvIHRyYWNrICU+JQogIAoKICAjIGFkZCB0aGUgZGF0YWZyYW1lIHRvIGEgbGlzdCAKICBPVFBfcmVzdWx0c1tbT1RQX2luZGV4XV0gPC0gdGhpc19kZgogIE9UUF9pbmRleCA8LSBPVFBfaW5kZXggKyAxCiAgCn0KCnByb2ZpdF9zdGF0ZXNfT1RQXzE0MjMgPC0gT1RQX3Jlc3VsdHNbWzFdXQoKZm9yIChPVFBfaW5kZXggaW4gc2VxKDIsIGxlbmd0aChPVFBfcmVzdWx0cykpKQp7CiAgcHJvZml0X3N0YXRlc19PVFBfMTQyMyA8LSBsZWZ0X2pvaW4ocHJvZml0X3N0YXRlc19PVFBfMTQyMywgT1RQX3Jlc3VsdHNbW09UUF9pbmRleF1dKQp9CgoKCmBgYApgYGB7cn0KcHJvZml0X3N0YXRlc19PVFBfMTQyMwpgYGAKCgoK